Why dio authenticated requests dont work? - flutter

When I use http package by passing bear token to the http request it works but not with Dio package. What I am doing wrong?
Dio _dio = Dio(BaseOptions(
baseUrl: baseUrl,
connectTimeout: 5000,
receiveTimeout: 100000,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization' : 'Bearer$bearToken'
}
)
);
FlutterSecureStorage storage = FlutterSecureStorage();
Future<String>get bearToken async{
return await storage.read(key: 'key').then((value) => value.toString());
}
log :
I/flutter ( 4648): Dio error!
I/flutter ( 4648): STATUS: 401
I/flutter ( 4648): DATA: {status: failed, error: Unauthenticated, code: 401}
I/flutter ( 4648): HEADERS: connection: close
I/flutter ( 4648): x-powered-by: PHP/8.0.7
I/flutter ( 4648): cache-control: no-cache, private
I/flutter ( 4648): date: Wed, 11 Aug 2021 12:58:29 GMT
I/flutter ( 4648): access-control-allow-origin: *
I/flutter ( 4648): host: 10.0.2.2:8000
I/flutter ( 4648): content-type: application/json

Firstly, u get the token asynchronously, so u need to await the result and store it to a variable.
Like this final token = await bearToken;
Secondly, add the space before token value. 'Bearer $bearToken'

Related

Getting FormatException response from my flutter api response

I have a button which when clicked, prints out response.
This is how the response is
{
"status": "success",
"user": "Worked well"
}
when I test it with postman it works fine, but when I try it from my flutter project, I get this error
I/flutter ( 5147): Response: - Instance of 'Response'
I/flutter ( 5147): FormatException: Unexpected character (at character 1)
I/flutter ( 5147): <!DOCTYPE html>
I/flutter ( 5147): ^
This is my flutter code:
http.Response response = await http.post(
Uri.parse(url + 'testMe.php'),
headers: headers,
body: body,
);
print('response ${response}');
if (response.body.isNotEmpty) {
json.decode(json.encode(response.body));
} else {
print('Response is empty...');
}
One thing I noticed is that, sometimes it does not throw the error above in flutter, it works fine and sometimes it throws the error, so I don't why it happen that way.
Flu
Postman Header
This worked for me:
Map<String, String> headers = {
'Content-Type': 'application/json',
'Charset': 'utf-8',
};
Your api return you a html instead of json, you can do this to avoid getting FormatException:
http.Response response = await http.post(
Uri.parse(url + 'testMe.php'),
headers: headers,
body: body,
);
print('response ${response}');
if (response.statusCode == 200) {
json.decode(response.body);
} else {
print('Response is empty...');
}
usually when statuscode is 500 or 404 this happened, when you check for status code 200, you can avoid getting this FormatException.
Also you don't need to encode the response and decode it again, your response is already encoded in server side, just decode it.

Having errors working with FormData flutter

I have been having a huge failure working with FormData using flutter. It works fine while I tested with postman which tells me the error is from my end. I need to post some list of files to the backend along with some parameters as such.
But it gives me 501 error each time which tells me that some data is invalid, however, there is no way to tell me exactly which parameter the error is located.
Dio dio = new Dio();
List<Map<String, int>> scheduled_slots = [
{"dateslot_id": 107, "timeslot_id": 97},
{"dateslot_id": 121, "timeslot_id": 120}
];
List<String> filesPath = ["/data/user/0/com.heckerbella.hope_clinic/app_flutter/1634521427103972"];
List<String> filesName = ["fileName"];
List<String> type =["Burning Pain", "Burning Pain"];
List<String> rating =["Just curious", "Mild Pain"];
FormData formData = FormData.fromMap({
"type": type,
"rating": rating,
"description": widget.description,
'files': [
await files.asMap().forEach((index, value) async {
await MultipartFile.fromFile
(filesPath[index], filename:
filesName[index]);
}),],
"scheduled_slots": scheduled_slots as String
});
try {
Response response = await dio.post(
Constants().API_BASE_URL +
"scheduled/slot/main/create/${selectedPlansData.id}",
data: formData,
options: Options(responseType: ResponseType.json, headers: {
"Authorization": "Bearer ${bloc.bearerToken}",
"Accept": "application/json",
}));
AlertManager.showToast(response.data.toString());
print(Constants().API_BASE_URL +
"scheduled/slot/main/create/${selectedPlansData.id}");
return response.data;
} catch (e) {
print(e.toString());
}
}
Error
I/flutter (10345): DioError [DioErrorType.response]: Http status error [501]
I/flutter (10345): #0 DioMixin.assureDioError (package:dio/src/dio_mixin.dart:819:20)
I/flutter (10345): #1 DioMixin._dispatchRequest (package:dio/src/dio_mixin.dart:678:13)
I/flutter (10345): <asynchronous suspension>
I/flutter (10345): #2 DioMixin.fetch.<anonymous closure>.<anonymous closure> (package:dio/src/dio_mixin.dart)
I/flutter (10345): <asynchronous suspension>
D/CompatibilityChangeReporter(10345): Compat change id reported: 147798919; UID 10146; state: ENABLED
E/Toast (10345): setGravity() shouldn't be called on text toasts, the values won't be used
You have issue with scheduled_slots, Dio only support fields on FormData is String, so when you pass a value is List<Map<String, int>>, Server will not receive it. Let deal with BE to convert scheduled_slots from List -> String.

flutter: send Authorization Token along http header

I am making a request in postman with the same URL that i use in my UI code and in the header passing accept and Authorization with bearer token. In postman it is working completely fine and giving desired response but in flutter in my code the token not send to server when i print my header using print(response.headers) it print {x-powered-by: Express, connection: keep-alive, keep-alive: timeout=5, date: Thu, 30 Sep 2021 16:47:57 GMT, content-length: 429, etag: W/"1ad-Nsvj6qTf+5iQsO/n7VuLkLMax/M", content-type: application/json; charset=utf-8} that means the Authorization part not send along the request header how can i send the authorization and token along to http post request ? please guide me it take my long hours but still not working.
here is my code:
var token='somethings';
response = await http.post(uri,
headers: {
'Content-Type': 'application/json; charset=UTF-8',
'Accept': 'application/json',
'authorization': 'Bearer $token',
},
body: jsonEncode(account[i]));
headers: {
HttpHeaders.authorizationHeader: 'Basic your_api_token_here',
},

Data isn't sending properly in dio , flutter

I am trying to pass token and username which I pass from login screen using sharedPreference in data, my api is working properly on postman it response successfully according to my requirement but it's still giving me Error on response.data.
here is my update code
Dio dio=new Dio();
var data={
'username': getname,
'token': getaccesstoken
};
await dio
.post(localhostUrlTimeIn,data: json.encode(data))
.then((onResponse) async {
print(onResponse.headers);
print(onResponse.statusCode);
print(onResponse.data);
}).catchError((onerror){
print(onerror.toString());
//showAlertDialog(context);
});
here are the logs
I/flutter (17731): 1
I/flutter (17731): x-powered-by: Express
I/flutter (17731): connection: keep-alive
I/flutter (17731): keep-alive: timeout=5
I/flutter (17731): date: Wed, 09 Jun 2021 21:07:41 GMT
I/flutter (17731): content-length: 7
I/flutter (17731): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (17731): content-type: application/json; charset=utf-8
I/flutter (17731): 200
I/flutter (17731): Error
----------------------------------UPDATED ------------------------
here is the backend code
TimeIn=(req,res)=>{
jwt.verify(req.body.token, 'secret' , function(err, decoded) {
if (err)
{
err["expiredAt"] = err["expiredAt"].toLocaleString();
res.status(300).json(err)
}else{
let today = new Date()
Today = today.toLocaleString();
var date = Today.split(",")
var document = new User();
User.find({"username":req.body.username},function(err,data){
var dat = date[0];
var da = dateformat(dat,"yyyy-mm-dd")
console.log(da);
document.username= data[0].username;
document.Date = da;
document.TimeIn = date[1];
document.TimeOut = "";
document.manager_id= data[0].manager_id,
document.code = data[0].code
document.save();
console.log(document);
var token = jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: "30 minute"})
res.status(200).json({auth: true, AccessToken: token})
})
}
})
}
and here i call above method in app.js file
const TimeIn = require('./routes/TimeInTimeOut')
app.post("/TimeIn",checkToken,function(req,res){
console.log("api hit")
TimeIn.TimeIn(req,res)
})
and here is where i am checking token,which is created in app.js file!!
function checkToken(req,res,result){
const header= req.body.token;
if(typeof header !== 'undefined'){
const bearer =header.split('.');
const token = bearer[1]
//console.log(token)
req.token = token
//next();
result();
}else
res.json("Error")
}
i am getting now this error in frontend
DioError [DioErrorType.response]: Http status error [300]
here is the postman output
and here is the backend output
Please help me, i have tried it too much but still getting error.
Your response is fully working. You do get data back and a 200 status code. This means the request was a succes. You are assigning error to the data in the request serverside. The issue isn't in your request in the client.
// headers
I/flutter (17731): 1
I/flutter (17731): x-powered-by: Express
I/flutter (17731): connection: keep-alive
I/flutter (17731): keep-alive: timeout=5
I/flutter (17731): date: Wed, 09 Jun 2021 21:07:41 GMT
I/flutter (17731): content-length: 7
I/flutter (17731): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (17731): content-type: application/json; charset=utf-8
//Statuscode
I/flutter (17731): 200
//data
I/flutter (17731): Error

Flutter dio http headers don't attach from interceptor

I have a Dio client with an interceptor attached, but when I try to add some headers, they don't appear in logs.
his is my code
Dio dio(KeyStore keyStore) {
final Dio dio = Dio(BaseOptions(
contentType: 'application/json',
connectTimeout: 5000,
sendTimeout: 5000,
));
final Dio tokenDio = Dio();
tokenDio.interceptors.add(LogInterceptor(responseBody: true));
dio.interceptors.add(LogInterceptor(responseBody: true));
dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) async {
final accessToken = await keyStore.readAccessToken();
final branchId = keyStore.readBranchId();
dio.lock();
options.headers[HttpHeaders.authorizationHeader] = 'Bearer: $accessToken';
options.headers['x-tenant'] = branchId;
handler.next(options);
dio.unlock();
}));
return dio;
}
Request headers...
I/flutter ( 8872): *** Request ***
I/flutter ( 8872): uri: https://api.someapi.com/users/058c026a-2dce-47e7-9fe1-61dec507265f
I/flutter ( 8872): method: GET
I/flutter ( 8872): responseType: ResponseType.json
I/flutter ( 8872): followRedirects: true
I/flutter ( 8872): connectTimeout: 5000
I/flutter ( 8872): sendTimeout: 5000
I/flutter ( 8872): receiveTimeout: 0
I/flutter ( 8872): receiveDataWhenStatusError: true
I/flutter ( 8872): extra: {}
I/flutter ( 8872): headers:
I/flutter ( 8872):
Dio interceptors are run in order. Since your auth interceptor is added after the log interceptor, LogInterceptor is called first, before the auth interceptor has a chance to add headers. The interceptor code looks fine to me, so I suspect that the authorization headers are correctly sent to the remote server.
To make your logs reflect the headers added by the auth interceptor, make sure LogInterceptor is the last element of the list dio.interceptors.
You don't necessarily need to use an interceptor.
You can update the default options like this:
dio.options.headers = {
HttpHeaders.authorizationHeader: 'Bearer: $accessToken',
'x-tenant': branchId
}
Then subsequent requests will use these values by default.