api response body doesn't show up - flutter

So I'm trying to get the access token from the Instagram API. it shows in Postman but it doesn't show up in the response body
onPageStarted: (url) async {
print("url is " + url);
if (url
.startsWith("https://aymen-ziouche.github.io/Gaming-website/")) {
Navigator.pop(context);
var uri = Uri.parse(url);
final String? code = uri.queryParameters["code"];
print("this's the code: $code");
final response = await dio
.post('https://api.instagram.com/oauth/access_token', data: {
'client_id': Constants.igClientId,
'client_secret': Constants.igClientSecret,
'grant_type': "authorization_code",
'redirect_uri': Constants.igRedirectURL,
'code': code
});
print("token is => ${response.data}");
print("response => ${response.statusCode} ${response.data}");
}
},
here's the log:
I/flutter (21891): url is https://aymen-ziouche.github.io/Gaming-website/?code=AQDIXj5sEEPfgHv_U5dcw3A9zQbWjR9w37MTWg9f153UAJsyHcG34iNtSgxH9sswpBvHrB1CobZBgReCx4GhCIeq5HiLfIDRe8c_HNS_U_7CQ5fVdP6JdS1vLxQua4iA706q9lik08r_C9aAFLm6oT0hJeQVXcHiwTqJWLxxyXxWhtmeClBYwlIoSJKp8gcf-rft6QrVOolBcXg6LCB6Vj9W7Dr3k4QiqsDVN0vX2uvAsw#_
I/flutter (21891): this's the code: AQDIXj5sEEPfgHv_U5dcw3A9zQbWjR9w37MTWg9f153UAJsyHcG34iNtSgxH9sswpBvHrB1CobZBgReCx4GhCIeq5HiLfIDRe8c_HNS_U_7CQ5fVdP6JdS1vLxQua4iA706q9lik08r_C9aAFLm6oT0hJeQVXcHiwTqJWLxxyXxWhtmeClBYwlIoSJKp8gcf-rft6QrVOolBcXg6LCB6Vj9W7Dr3k4QiqsDVN0vX2uvAsw
I/flutter (21891): token is =>
I/flutter (21891): response => 200
I fixed it. the problem was in dio.options() I added this: Options(responseType: ResponseType.json)

Add “Content-Type”: “application/json” and “Accept”: “application/json” to the headers parameters of your dio.post() method

According to the package example, you should use response.data.toString() if you want to print it.
If you want to use it, properly decode it first.

Related

Response body is empty in http call

I am calling a remote PHP file to get some data into my Flutter app.
This is the Flutter function:
Future<void> registrarUsuario() async {
var url = Constantes.adminUsuariosUrl + 'nuevo_usuario.php';
final response = await http.post(Uri.parse(url), body: {
"email": controllerEmail.text,
"password": controllerPass.text
});
print("response ${response.body}");
}
Calling the function the print output is empty.
flutter: response
But calling the PHP file using Postman gives me the following output:
[{"id":"57","correo":"modestovasco#gmail.com"}]
I would like to update the funtion registrarUsuario to get the json objects from the response.body
Encode the body content in request
Future<void> registrarUsuario() async {
var url = Constantes.adminUsuariosUrl + 'nuevo_usuario.php';
final response = await http.post(Uri.parse(url), body:json.encode({
"email": controllerEmail.text,
"password": controllerPass.text
}));
print("response ${response.body}");
}

Client Login using Flutter for Mediawiki

I am in the learning proess for both flutter and requests so forgive me if it is a simple mistake. I am trying to make a client login to a mediaiwki instance using client login api. I can fetch the login token succesfully but when I try to login it says invalid csrf token it gives {"error":{"code":"badtoken","info":"Invalid CSRF token.","*":". The api I am using to login is as follows.
https://www.mediawiki.org/wiki/API:Login#Method_2._clientlogin
Thanks for your help.
To fetch login token succesfully I use
_fetch_login_token() async {
Map<String, String> headers = {"Content-type": "application/json"};
Map<String, String> body = {
'action': "query",
'meta': "tokens",
'type': "login",
'format': "json"
};
Response response = await post(
url,
body: body,
);
//print(response);
// int statusCode = response.statusCode;
// print(statusCode);
var decoded = jsonDecode(response.body);
print(decoded);
var jsonsData = response.body; // toString of Response's body is assigned to jsonDataString
var data = jsonDecode(jsonsData);
var token=data['query']['tokens']['logintoken'];
return _makePostRequest(token);
}
And my failed login as follows
Map<String, String> body = {
'action': "clientlogin",
'username': username,
'password': password,
'loginreturnurl': url,
'logintoken': loginToken,
'format': "json"
};
Response response = await post(
url,
body:body,
);
I solved the problem.For future reference, I have downloaded dio package and added intercepter and cookie manager in order to persist the cookies.

How to post x-www-form-urlencoded in Flutter

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 :
Bulk Edit Mode :
Key-Value Edit mode :
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)
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.
}
}
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),
);
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:
MDN: 307 Temporary Redirect
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
}
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);
}
If you are using http, you should add the below lines
Android -
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="first_app"
android:usesCleartextTraffic="true" //this line
android:icon="#mipmap/ic_launcher">
iOS -
ios/Runner/info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Be warned that you will need to have an explanation for Apple's review team when enabling this, otherwise, your app will get rejected on submission.
Uninstall the app and Reinstall again if you have the app already in the emulator when you add those lines to avoid confusions.
If you send HTTP GET request, you can use query parameters as follows:
QueryParameters
http://example.com/path/to/page?name=ferret&color=purple
The contents are encoded as query parameters in the URL
application/x-www-form- urlencoded
The contents are encoded as query parameters in the body of the
request instead of the URL.
The data is sent as a long query string. The query string contains
name-value pairs separated by & character
POST example
flutter http package version - http: ^0.13.1
import 'package:http/http.dart' as httpClient;
Future<dynamic> postData() async {
//Uri.https("192.168.1.30:5000", "/api/data")
//Uri.parse("your url");
final Uri uri = Uri.http("192.168.1.30:5000", "/api/data");
final response = await httpClient.post(
uri,
body: {
"name": "yourName",
"age": "yourAge"
},
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
encoding: Encoding.getByName('utf-8'),
);
return response.body;
}

I am not able to upload images and form data to rest api using DIO package in flutter

I am not able to upload image to rest api in flutter I have checked the api its working fine.
I am not able to convert the file (image) to a uploadable form, can any one help me with that?
I have run flutter doctor -v everything is fine :)
Here is the code I am using to post form data:
Future<void> uploadAccountDetails(AccountDetailsModel details) async {
var url = baseUrl + '/api/uploads/images';
try {
Dio dio = new Dio();
FormData formData = new FormData.fromMap(
{
'city': details.cityName,
'country': details.countryName,
'residence_address': details.address,
'dob': details.dob,
'id_num': details.id,
'passport_num': details.passportNo,
'driving_license_nim': details.drivingLicNo,
'user_id': 162,
'postal_code': details.postalCode,
'id_pic': await MultipartFile.fromFile(details.idPic.path,
filename: basename(details.idPic.path)),
'driving_license_pic':
await MultipartFile.fromFile(details.drivingLicPic.path,
filename: basename(
details.drivingLicPic.path,
)),
'birth_certificate': await MultipartFile.fromFile(
details.drivingLicPic.path,
filename: basename(details.birthCertPic.path),
),
'residence_permit_pic': await MultipartFile.fromFile(
details.resPermitPic.path,
filename: basename(details.resPermitPic.path),
),
'profile_pic': await MultipartFile.fromFile(details.profilePic.path,
filename: basename(details.profilePic.path)),
},
);
print(formData);
Response response = await dio.post(
url,
data: formData,
onSendProgress: (received, total) {
if (total != -1) {
print((received / total * 100).toStringAsFixed(0) + "%");
}
},
);
print(response.statusCode);
// print(response);
} catch (e) {
print(e);
throw (e);
}
}
The logs of error are as follows:
I/flutter (22523): DioError [DioErrorType.RESPONSE]: Http status error
[500] I/flutter (22523): DioError [DioErrorType.RESPONSE]: Http status
error [500]
The status error is:
I/flutter (22523): DioError [DioErrorType.RESPONSE]: Http status error
[500]
I searched this error but didnt find any solution, can anyone help me with that?
I used dio for post a file path with some other information in this way:
Dio dio = new Dio();
FormData formData = new FormData();
formData.add(
"apiKey",
"my_api_key",
);
formData.add(
"file",
"image_path",
);
Response response = await dio.post(
"https://localhost",
data: formData,
onSendProgress: (int sent, int total) {
// do something
},
).catchError((onError) {
throw Exception('something');
});

Get Access Token with REST API in flutter/dart

I cannot take access token with this getData() function, it return "Bad Request - Invalid Hostname". How can ı fix this problem ? Am ı change Future<> method, async or http methods ?
Here is my main.dart :
Future<HttpClient> getData() async {
Map<String, String> connection = {
'grant_type': 'string',
'branchcode': 'string',
'password': 'string',
'username': 'string',
'dbname': 'string',
'dbuser': 'string',
'dbpassword': 'string',
'dbtype': 'string+'
};
var uri = Uri.http("192.168.1.44:7070","api/v2/token",connection);
http.Response r = await http.get(uri);
print(r.statusCode);
print(r.body);
}
ERROR !
I/flutter ( 9316): 400
I/flutter ( 9316): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
I/flutter ( 9316): <HTML><HEAD><TITLE>Bad Request</TITLE>
I/flutter ( 9316): <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
I/flutter ( 9316): <BODY><h2>Bad Request - Invalid Hostname</h2>
I/flutter ( 9316): <hr><p>HTTP Error 400. The request hostname is invalid.</p>
I/flutter ( 9316): </BODY></HTML>
If you want to get token from rest api you have to post your connection with http.post() method.In this method you can easily declare the connection string in body field.I tried and it is working.
Here is my code block:
Future<Null> getData() async {
var url = "http://192.168.1.23:7070/api/v2/token";
http.post(url, body:{
"grant_type": "string",
"branchcode": "string",
"password": "string",
"username": "string",
"dbname": "string",
"dbuser": "string",
"dbpassword": "string",
"dbtype": "string"
}).then((response){
print("Response Status: ${response.statusCode}");
print("Response Body: ${response.body}");
});
}
I have tried to get the access token using unsplash api and it worked fine. I have used two plugins. first one, url_launcher, it allows you to open the url in a browser. you should put the registration url and once the user has successfully registered, user is redirected to your app. how? using the second plugin uni_links. once the user return back you start to extract the access token.
Launch the url that allow user to register
_launchURL() async {
var registerUrl= Constants.registerUrl;
if (await canLaunch(registerUrl)) {
await launch(registerUrl);
} else {
throw 'Could not launch $loginUrl';
}
}
when the user finish the process. your app should listen for this step
#override
initState() {
super.initState();
initUniLinks();
}
Future<Null> initUniLinks() async {
getUriLinksStream().listen((Uri uri) {
if (uri != null) {
setState(() {
String code = uri.queryParameters["code"];
print("code:" + code);
if (code != null) {
_getAccessToken(Constants.clientId, Constants.clientSecret,
Constants.redirectURI, code, "authorization_code");
}
});
}
}, onError: (err) {
print("error:" + err.toString());
});
}
_getAccessToken(String client_id, String client_secret, String redirect_uri,
String code, String grant_type) async {
var url = "https://unsplash.com/oauth/token";
var query_params = {
"client_id": client_id,
"client_secret": client_secret,
"redirect_uri": redirect_uri,
"code": code,
"grant_type": grant_type
};
var response = await http.post(url, body: query_params);
Map<String, dynamic> map = json.decode(response.body);
var accessToken = AccessToken.fromJson(map);
_saveAccessTokenToPrefs(accessToken);
}