Getting invalid response on data of api using dio in flutter - flutter

i want to pass username and token from login screen to dashboard, i saved it using sharedpreference and call it to dashboard, i'm getting values too. but when i pass them to my api, using dio and print it's response.data it gives me Error wherease it's statuscode is 200. kindly help me with to fix this issue.
here is my code
var localhostUrl="http://10.0.2.2:8000/TimeIn";
_userDetails() async{
SharedPreferences myPrefs=await SharedPreferences.getInstance();
setState(() {
getname=myPrefs.getString('name');
getdesignation=myPrefs.getString('designation');
getTimeInStatus=myPrefs.getBool('timeInStatus');
getaccesstoken=myPrefs.getString('accesstoken');
});
}
calltimeInApi() async {
Dio dio=new Dio(
BaseOptions(
connectTimeout: 30000,
baseUrl: localhostUrl,
responseType: ResponseType.json,
contentType: ContentType.json.toString(),
));
var data={
'username':getname
};
dio.options.headers["authorization"] = "Bearer ${getaccesstoken}";
await dio.post(localhostUrl,data: data).then((onResponse) async {
print(onResponse.headers);
print(onResponse.statusCode);
print(onResponse.data);
;
});}
here is the output
I/flutter (14995): 1
I/flutter (14995): x-powered-by: Express
I/flutter (14995): connection: keep-alive
I/flutter (14995): keep-alive: timeout=5
I/flutter (14995): date: Wed, 09 Jun 2021 18:34:53 GMT
I/flutter (14995): content-length: 7
I/flutter (14995): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (14995): content-type: application/json; charset=utf-8
I/flutter (14995): 200 //statuscode
I/flutter (14995): Error //data
-----------Updated
i have tried all possible answers which i got from internet but no one resolves my problem
calltimeInApi() async {
Dio dio=new Dio(
BaseOptions(
connectTimeout: 30000,
baseUrl: localhostUrlTimeIn,
headers: {"Accept":"application/json"}
//contentType: ContentType.json.toString(),
));
var data={
"username":getname
};
dio.options.headers["authorization"] = "Bearer ${getaccesstoken}";
await dio.post(localhostUrlTimeIn,data: json.encode(data)).then((onResponse) async {
print(onResponse.headers);
if (onResponse.statusCode == 200) {
print(json.decode(onResponse.data));
} else {
print(onResponse.statusCode);
}
//print(onResponse.statusCode);
//print(json.decode(onResponse.data));
// print(response.statusCode);
// print(response.headers);
// print(response.statusMessage);
// print(response.data);
});}
here are logs of the above updated code
I/flutter (14995): 1
I/flutter (14995): x-powered-by: Express
I/flutter (14995): connection: keep-alive
I/flutter (14995): keep-alive: timeout=5
I/flutter (14995): date: Wed, 09 Jun 2021 19:20:41 GMT
I/flutter (14995): content-length: 7
I/flutter (14995): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (14995): content-type: application/json; charset=utf-8
E/flutter (14995): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter (14995): Error
E/flutter (14995): ^
E/flutter (14995):
-----------------------------------UPDATED-----------------------------
i try to pass token in data, my api is working properly it response successfully according to my requirement but it's still giving me Error on response.data.
here is my update code
calltimeInApi() async {
Dio dio=new Dio();
var data={
'username': getname,
'token': getaccesstoken
};
await dio
.post(localhostUrlTimeIn,data: json.encode(data))
.then((onResponse) async {
print(onResponse.data);
print(onResponse.headers);
print(onResponse.statusCode);
}).catchError((onerror){
print(onerror.toString());
//showAlertDialog(context);
});
}
please help if anyone know how to fix it

//editing your dio
Dio createDio() {
//configure dio
Dio dio = Dio(BaseOptions(
connectTimeout: 50000,
receiveTimeout: 50000,
baseUrl: ApiPaths.BASE_URL,
));
;
//add interceptors
dio.interceptors.add(InterceptorsWrapper(
onRequest: (Options options, handler) async {
print('send request:path:${options.path},baseURL:${options.baseUrl}');
//==============fetch your token and parse it here as csrfToken============
if (csrfToken == null) {
print('no token,request token firstly...');
//lock the dio.
dio.lock();
//token null , try getting new token
handler.next(options);
}).catchError((error, stackTrace) {
handler.reject(error, true);
}) .whenComplete(() => dio.unlock()); // unlock the dio
} else {
//here add your token
options.headers["authorization"] = "Bearer $csrfToken";
handler.next(options);
}
}
));
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
final isValidHost = host == ApiPaths.BASE_URL;
return true;
};
return client;
};
return dio;
}
var dioHelper = createDio();
Edit your dio.post to match this . You nolonger need to create dio again. Anywhere you need to access dio use dioHelper
Response response= await dioHelper.post(localhostUrlTimeIn,data: json.encode(data));
print(response.statusCode)
print(response.data)
//you decode when parsing to an object model

Related

How to solve this dio library error? Flutter/Dart

Hello there i am trying to download a pdf file with dio library but in the end i get this errror:
Hello there i am trying to download a pdf file with dio library but in the end i get this errror:
I/flutter (19900): 100%
I/flutter (19900): connection: keep-alive
I/flutter (19900): last-modified: Mon, 17 Oct 2022 10:17:34 GMT
I/flutter (19900): cache-control: no-cache, no-store, max-age=0, must-revalidate
I/flutter (19900): date: Fri, 21 Oct 2022 07:39:15 GMT
I/flutter (19900): vary: Origin
I/flutter (19900): vary: Access-Control-Request-Method
I/flutter (19900): vary: Access-Control-Request-Headers
I/flutter (19900): content-type: text/html;charset=UTF-8
I/flutter (19900): pragma: no-cache
I/flutter (19900): x-xss-protection: 1; mode=block
I/flutter (19900): content-language: en
I/flutter (19900): server: nginx/1.15.12
I/flutter (19900): accept-ranges: bytes
I/flutter (19900): content-length: 6425
I/flutter (19900): x-frame-options: DENY
I/flutter (19900): x-content-type-options: nosniff
I/flutter (19900): expires: 0
I/flutter (19900): FileSystemException: Cannot open file, path = '/data/user/0/com.iccs.electromobilityapp/cache' (OS Error: Is a directory, errno = 21)
Here is my code:
Future download2(Dio dio, String url, String savePath) async {
Directory tempDir = await getTemporaryDirectory();
tempPath = tempDir.path;
String? token = await this.widget.appController.storage.read(key: "token");
Map<String, String> headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + (token ?? ""),
};
try {
Response response = await dio.get(
url,
onReceiveProgress: showDownloadProgress,
//Received data with List<int>
options: Options(
headers: headers,
responseType: ResponseType.bytes,
followRedirects: false,
validateStatus: (status) {
return status! < 500;
}),
);
print(response.headers);
new File('$tempPath/file.xlsx').create(recursive: true);
File file = File(tempPath);
var raf = file.openSync(mode: FileMode.write);
// response.data is List<int> type
raf.writeFromSync(response.data);
await raf.close();
} catch (e) {
print(e);
}
}
I've written a simple function for you just pass a url and filename as an argument
downloadedFile({required String url, required String filename}) async {
var downloadsDirectoryPath = await getTemporaryDirectory()
final File file = File("/${downloadsDirectoryPath!.path}/$filename");
final response = await Dio().get(url, onReceiveProgress: (received, total) {
},
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
receiveTimeout: 0,
));
final raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(response.data);
await raf.close();
return file;
}
Note: upvote and make the answer as correct if you find it useful.

api response body doesn't show up

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.

401 on POST requests, how to set up properly http service?

I am trying to fetch data after successful login. I have cookie based auth on backend. I checked the login response and I see that the cookie is present in the headers. I am not sure why my requests are not going with cookie.
I keep getting this in my console, code for not authorized. I/flutter (21293): 401
class Session {
Map<String, String> headers = {};
Future<Map> get(String endpoint) async {
http.Response response = await http.get(Uri.parse("$baseUrl$endpoint"), headers: headers);
print(response.statusCode);
updateCookie(response);
return jsonDecode(response.body);
}
Future<http.Response> post(dynamic data, String endpoint) async {
http.Response response = await http.post(Uri.parse("$baseUrl$endpoint"), body: json.decode(data), headers: headers);
updateCookie(response);
return response;
}
void updateCookie(http.Response response) {
String? rawCookie = response.headers['set-cookie'];
if (rawCookie != null) {
int index = rawCookie.indexOf(';');
headers['cookie'] =
(index == -1) ? rawCookie : rawCookie.substring(0, index);
}
}
}
Tried to print rawCookie as well
I/flutter (21293): _api_key=SFMyNTY.g3QAAAABbQAAAAhpZGVudGl0eXQAAAAHZAAKX19zdHJ1Y3RfX2QAF0VsaXhpci5HYXRld2F5LklkZW50aXR5ZAAGYWN0aXZlZAAEdHJ1ZWQACWF2YXRhcl9pZG0AAAAkNTY4NWMwNTMtYThhMS00MDA5LWJhN2UtZmJkNTkyMjBhM2U1ZAAHY291bnRyeXQAAAAGZAAEZmxhZ20AAAAI8J-HtfCfh7FkAAppc29fbmFtZV8ybQAAAAJwbGQACmlzb19uYW1lXzNtAAAAA3BvbGQABG5hbWVtAAAABlBvbGFuZGQACG51bV9jb2RlbQAAAAM2MTZkAAVwb2ludHQAAAAEZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5HZW8uUG9pbnRkAAtjb29yZGluYXRlc2gCYRRhNGQACnByb3BlcnRpZXN0AAAAAGQABHNyaWRiAAAQ5mQAC2Rlc2NyaXB0aW9ubQAAAAF4ZAACaWRtAAAAJGM2ZTljY2Q0LTM4MmItNDEzZi04ODYyLTc2ZjM5ZTYxOGFiNGQABG5pY2ttAAAACHRlc3Rzc3Nz.80iQK3sUwPPVj1pkaZsKgMxQ4Lt8aW8-ndYbPSucGag; path=/; HttpOnly
I/flutter (21293): 200
Then I use it
class Items{
Future<Map> fetchItems() async {
final response = await Session().get("/user/items");
return response;
}
}
I had the same problem. I resolved it by using dio and cookiejar instead of HTTP.
Add these dependencies in your pubspec.yaml:
dependencies:
dio: ^4.0.4
dio_cookie_manager: ^2.0.0
cookie_jar: ^3.0.1
Here's an example to use dio:
var dio = Dio(BaseOptions(
connectTimeout: 10000, // in ms
receiveTimeout: 10000,
sendTimeout: 10000,
responseType: ResponseType.plain,
followRedirects: false,
validateStatus: (status) { return true; }
)); // some dio configurations
dio.interceptors.add(CookieManager(CookieJar()));
Response response = await dio.post(
"http://example.com/login",
data: FormData.fromMap(
{
'username': 'myUser',
'password': 'myPassword',
}
)); // cookies are automatically saved
Response nextResponse = await dio.post("http://example.com/user/items");

DioError [DioErrorType.response]: Http status error [401]

final dio = Dio();
try {
await dio.request(
'https://api.example.com/api/v1/auth/validateMobile',
data: {"phoneNo": "+91999999999"},
options: Options(
method: 'GET',
headers: {
HttpHeaders.authorizationHeader:
'Bearer $token',
'content-Type': 'application/json'
},
),
);
} on DioError catch (e) {
print(e);
}
I/flutter (16336): DioError [DioErrorType.response]: Http status error [401]
I/flutter (16336): #0 DioMixin.assureDioError (package:dio/src/dio_mixin.dart:819:20)
I/flutter (16336): #1 DioMixin._dispatchRequest (package:dio/src/dio_mixin.dart:678:13)
I/flutter (16336): <asynchronous suspension>
I/flutter (16336): #2 DioMixin.fetch.<anonymous closure>.<anonymous closure> (package:dio/src/dio_mixin.dart)
I/flutter (16336): <asynchronous suspension>
I'm getting 401 error even though I'm passing authorization header with correct token. Thank you for your help.
Use this parameter along with other option parameters, it worked for me, I hope it works for you too
Options (validateStatus: (_) => true)
If it does not work, you can try this
Options (
validateStatus: (_) => true,
contentType: Headers.jsonContentType,
responseType:ResponseType.json,
)
you should pass content-type like this:
HttpHeaders.contentTypeHeader: 'application/json'
here is an example of using this instead of Dio:
fetchSearchedNews(String searchParameter) async {
final queryParameters = {
'keywords': searchParameter,
};
final uri = Uri.https('$baseUrl', '/v1/search', queryParameters);
final response = await http.get(uri, headers: {
HttpHeaders.authorizationHeader:
'YOUR KEY HERE',
HttpHeaders.contentTypeHeader: 'application/json',
});
print(response.statusCode);
if (response.statusCode == 200) {
final items = json.decode(response.body);
return NewsModel.fromJson(items).news;
} else if (response.statusCode == 401) {
throw Exception('Error 401');
} else if (response.statusCode == 429) {
throw Exception('Error 429');
} else {
throw Exception('null');
}
}
The solution is simple, surround your request with a try catch of dio as follows
try{
//put your dio request here....
} on DioError catch(e){
// in case of a code that is not success, you can get it here through object 'e'
}
THANK ME LATER!

Getting Blank httpException message while trying to pass client certificate with dio

I am getting blank httpException message while trying to submit client certificate by using Dio package.
DioErrorType (DioErrorType.DEFAULT) : HttpException (HttpException: , uri = [API_PATH])
Same certificate is working when requesting with postman.
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Thu, 21 Jan 2021 05:56:55 GMT
Below is the code I am using
Future<List<int>> loadCertificate(String assetPath) async {
return (await rootBundle.load(assetPath)).buffer.asUint8List();
}
final List<int> certificateChainBytes =
await loadCertificate('assets/certs/client-cert1.pfx');
final List<int> keyBytes =
await loadCertificate('assets/certs/client-cert1.pfx');
final Dio dio = Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
final SecurityContext sc = SecurityContext()
..useCertificateChainBytes(certificateChainBytes, password: 'Secret')
..usePrivateKeyBytes(keyBytes, password: 'Secret');
final HttpClient httpClient = HttpClient(context: sc);
httpClient.badCertificateCallback =
(X509Certificate cert, String host, int port) {
print('badcertificatecallback');
print(cert.issuer);
return true;
};
return httpClient;
};
try {
url = url.contains('http') ? url : '${PsConfig.ps_app_url}$url';
print('API Response from $url');
final Response response =
await dio.get(url, options: Options(headers: getHeaders()));
return processHttpResponse(obj, response);
} on diolib.DioError catch (e) {
inspect(e);
return processDioResponse(obj, e);
} finally {
dio.close();
}
I am new to this and got stuck. Thank you in advance.