How to post x-www-form-urlencoded in Flutter
Solution 1
For x-www-form-urlencoded
parameters, just use this:
Future<String> login(user, pass) async {
final response = await http.post(
Uri.parse('https:youraddress.com/api'),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
encoding: Encoding.getByName('utf-8'),
body: {"title": "title"},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
}
}
Solution 2
official http
package from flutter is buggy with urlencoded
type, you can use Dio package instead.
final dio = Dio();
final res = dio.post(
'/info',
data: {'id': 5},
options: Options(contentType: Headers.formUrlEncodedContentType),
);
Solution 3
As you can see, I am getting a 307 error, and the problem does not come from the server, as it worked with Postman.
No, that's NOT necessarily the case. Look here:
In other words, Postman is following the redirect ... and your Flutter app isn't.
SUGGESTION: Try setting followRedirects
to true:
https://api.flutter.dev/flutter/dart-io/HttpClientRequest/followRedirects.html
ADDITIONAL INFO:
The default value for
request.followRedirects
happens to be "true" anyway. It doesn't hurt to explicitly set it ... but it explains why the behavior didn't change.Per this post:
The Dart HTTP client won't follow redirects for POSTs unless the response code is 303. It follows 302 redirects for GET or HEAD.
- Per this post
The correct way to handle redirects on POST requests is to manually implement an appropriate strategy for your use case:
var response = await client.post(...); if (response.statusCode == 301 || response.statusCode == 302) { // send post request again if appropriate }
Solution 4
let try with this code, it works well for me.
var headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var request = http.Request('POST', Uri.parse('https://oauth2.googleapis.com/token'));
request.bodyFields = {
'client_id': '',
'client_secret': '',
'code': '',
'grant_type': 'authorization_code',
'redirect_uri': ''
};
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
Mathieu
I am currently working at Octo as an Android Developer. During my studies in 42born2code school, I learned C language, especially UNIX system programmation. In my internship and apprenticeships, I have done Android Development. I have a tons of ideas of mobile apps, but not enough time to bring them to live for now. I am passionated about house automation, "bionic", robotic, drone... I want to learn about Lineage OS.
Updated on November 28, 2022Comments
-
Mathieu over 1 year
I am trying to send a
POST
request to an API to create an account.
The request is working well, it should look like this :There are also 9 headers that are auto-generated, so I did not show them, but I can take another screen if you need to.
My request looks like this :
import 'dart:convert' as convert ; import 'package:my_project/requests/utils.dart'; import 'package:http/http.dart' as http; Future<String> createUser(String firstName, String name, String mail, String password, String confirmPassword, String birthDate, String phone) async { String url = BASE_URL + "createUser" ; // Don't worry about BASE_URL, the final url is correct Map<String, dynamic> formMap = { "name": name, "surname": firstName, "mail": mail, "password": password, "birth": birthDate, "phone": phone, "confirmPassword": confirmPassword } ; http.Response response = await http.post( url, body: convert.jsonEncode(formMap), headers: { "Content-Type": "application/x-www-form-urlencoded" }, encoding: convert.Encoding.getByName("utf-8"), ); print("RESPONSE ${response.statusCode} ; BODY = ${response.body}"); return (response.body) ; }
Here is my print result :
I/flutter ( 6942): RESPONSE 307 ; BODY =
As you can see, I am getting a 307 error, and the problem does not come from the server, as it worked with Postman.
Am I sending this
form-urlencoded POST
request correctly ?I also tried :
http.Response response = await http.post( url, body: "name=$name&surname=$firstName&mail=$mail&password=$password&birth=$birthDate&phone=$phone&confirmPassword=$confirmPassword", headers: { "Content-Type": "application/x-www-form-urlencoded" }, encoding: convert.Encoding.getByName("utf-8"), );
but with the same results. I tried too :
http.Response response = await http.post( url, body: formMap, headers: { "Content-Type": "application/x-www-form-urlencoded" }, encoding: convert.Encoding.getByName("utf-8"), );
with same result again.
What am I doing wrong ?EDIT :
I tried FoggyDay answer, here is my request now :
final client = HttpClient() ; final request = await client.postUrl(Uri.parse(url)); request.headers.set(HttpHeaders.contentTypeHeader, "application/x-www_form-urlencoded"); request.followRedirects = true ; request.write(formMap); final response = await request.close(); print("STATUS CODE = ${response.statusCode}");
However I still have a 307 error. Did I create the right request ?
EDIT 2 :
As asked, I printed location as follow :
final client = HttpClient() ; final request = await client.postUrl(Uri.parse(url)); request.headers.set(HttpHeaders.contentTypeHeader, "application/x-www_form-urlencoded"); request.followRedirects = true ; request.write(formMap); final response = await request.close(); print("STATUS CODE = ${response.statusCode}"); print("Response headers = ${response.headers}");
And I get :
I/flutter ( 7671): STATUS CODE = 307 I/flutter ( 7671): Response headers = location: /app/createUser/ I/flutter ( 7671): date: Tue, 26 May 2020 09:00:29 GMT I/flutter ( 7671): content-length: 0 I/flutter ( 7671): server: Apache/2.4.41 (Amazon) OpenSSL/1.0.2k-fips
The thing is I am already making a call on /app/createUser... ('/app/' is in BASE_URL)
-
Richard Heap almost 4 yearsYour third syntax is correct, and you don't need the content type header, it will be added for you. Why not use something like wireshark to see what the 3xx response points to. The great thing about package http is that you can use it in a plain dart program running on your development machine, as long as you download the day SDK. This is often the fastest way to try http requests and JSON parsing etc.
-
Richard Heap almost 4 yearsAlternatively, print out the received Location header.
-
Mathieu almost 4 yearsI have edited my question. The location header point to the same address of where I am making the call.
-
Karitsa over 3 yearsPretty old question, but looks like you are redirected from /app/createUser to /app/createUser/ (Notice last /), it is different thing in some cases
-
-
Mathieu almost 4 yearsI tried your answer and edited my question to show you the current code. Unfortunately I still get this 307...
-
Mathieu almost 4 yearsThis is a strange way to do, but if it works it would be great. However the redirect address seems to be exactly the same than the one I am using to make the original call :/
-
ZhangLei almost 4 yearsHttp status code 307 and 308 should also be handled manually for POST requests.
-
Arslan Kaleem almost 2 yearsdidn't work for me