Reusing http headers - flutter

I'm trying to find a best way to reuse http headers in my http responses. Instead of writing it in string literal
final http.Response response = await http.post(APIPath.somePath(),
headers:{"Content-Type": "application/json","Authorization": "Bearer $_token"},
body: json.encode(body));
I have made a custom class and get each header into a static function
class APIHeader {
static Map<String, String> json() => {"Content-Type": "application/json"};
static Map<String, String> form() => {"Content-Type": "multipart/form-data"};
static Map<String, String> authorization(String token) =>
{"Authorization": "Bearer $token"};
}
and call them wherever I need them which work great if there is only one header needed
final http.Response response = await http.put(APIPath.somePath(),
headers: APIHeader.json(), body: json.encode(body));
However I'm having a trouble if I need more then one header. I tried this..
final header = {}
..addAll(APIHeader.authorization(_token))
..addAll(APIHeader.json());
final http.Response response = await http.post(APIPath.somePath(),
headers: header, body: json.encode(body));
which gives me an error
Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, String>'
Anyone have better idea how to reuse the headers?

Thanks to #pskink I found using mergeMaps from 'package:collection/collection.dart' the best way to reuse headers and merge them into one map
final http.Response response = await http.post(APIPath.somePath(),
headers: [APIHeader.authorization(_token), APIHeader.json()]
.reduce(mergeMaps),
body: json.encode(body));

Related

Fail to get http response with form-data

I am not able to get response from http POST in Flutter but URL and data are verified in Postman.
var map = new Map<String, String>();
final url = Uri.parse(globals.ServerDomain + '/login');
Map<String, String> requestBody = <String, String>{
'username': '80889099',
'password': '123456789abcde'
};
var request = http.MultipartRequest('POST', url)
..fields.addAll(requestBody);
var response = await request.send();
final respStr = await response.stream.bytesToString();
print(respStr);
no result returned.
Flutter has this great package called Dio to handle all sort of http requests. It's very easy to do what you want with it, you are using form data so this is what you should use. For more details check this https://pub.dev/packages/dio#sending-formdata
Example code:
final formData = FormData.fromMap(
{'username': '80889099',
'password': "123456789abcde",
});
final response = await dio.post('${globals.ServerDomain}/login', data: formData);
Looks like Its big project changing the package is not a good option try adding request header
'Content-Type': 'multipart/form-data'
example code :
Map<String, String> headers= <String,String>{
'Authorization':'Basic ${base64Encode(utf8.encode('user:password'))}',//your any other header
'Content-Type': 'multipart/form-data'
};
var map = new Map<String, String>();
final url = Uri.parse(globals.ServerDomain + '/login');
Map<String, String> requestBody = <String, String>{
'username': '80889099',
'password': '123456789abcde'
};
var request = http.MultipartRequest('POST', URL)
..headers.addAll(headers)
..fields.addAll(requestBody);
var response = await request.send();
final respStr = await response.stream.bytesToString();
print(respStr);
Additionally check if internet permission is given (may not be the cause just info)

Unable to send header information with client.post

I'm trying to pass along a bearer token and refresh token to an endpoint in Flutter but I'm getting errors no matter what I try. The api endpoint does work with Postman and returns a new token so the issue is with Flutter.
Future<List<PetsList>> fetchPets(http.Client client) async {
var _headers = {
'Content-Type': 'application/json',
'token': singleton.token,
'refreshToken': singleton.refreshToken,
};
var encodedHeader = json.encode(json.encode(_headers));
final response = await client.post(
Uri.parse(baseUrl + '/account/refreshtoken'),
headers: encodedHeader);
print("${response.body}");
};
This threw an error and stated that "The argument type 'String' can't be assigned to the parameter type 'Map<String, String>?'"
So I appended encodedHeader as Map<String, String> in the response
encodedHeader as Map<String, String>
but that then threw another error, "_CastError (type 'String' is not a subtype of type 'Map<String, String>' in type cast)"
Lastly, the response.body throws an error when I try to simply
print("${response.body}");
and states "Object reference not set to an instance of an object."
No matter what I've tried Flutter complains about this, I seem to be going in circles on this one and could use some help.
The headers require a map<string, string> if you json encode it then it becomes a single string. Please remove the encode
Future<List<PetsList>> fetchPets(http.Client client) async {
Map<String, String> _headers = {
'Content-Type': 'application/json',
'token': singleton.token,
'refreshToken': singleton.refreshToken,
};
final response = await client.post(
Uri.parse(baseUrl + '/account/refreshtoken'),
headers: _headers);
};

In flutter I am unable to connect to API, When I test it works well but from flutter it is not working?

Future predictCluster(List<List<int>> scores) async {
String url = 'http://127.0.0.1:5000/predict';
Uri uri = Uri.parse(url);
Response response = await post(uri, body: (scores));
Map<String, dynamic> prediction = json.decode(response.body);
cluster = int.parse(prediction["predicted_cluster"][0]);
notifyListeners();
}
Here I have to send a list of list with integers as per API but getting rejected by casting when I am using encode methods I am getting a Format exception.
This is the api.
Getting Error for line
Response response = await post(uri, body: (scores));
Error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'List' is not a subtype of type 'int' in type cast
The problem is, probably, that your emulator doesn't reach your API on your local machine.
The url should instead be:
String url = 'http://10.0.2.2:5000/predict';
Future predictCluster(List<List<int>> scores) async {
String url = 'http://10.0.2.2:5000/predict';
Uri uri = Uri.parse(url);
final encodedData = jsonEncode(<String, dynamic>{
"score": scores,
});
Response response = await post(
uri,
headers: {"Content-Type": "application/json"},
body: encodedData,
);
Map<String, dynamic> prediction = json.decode(response.body);
cluster = int.parse(prediction["predicted_cluster"][0]);
notifyListeners();
}
We have to send through the map structure to encode data and also mention the header content type to application/json.

Submit array in http flutter

This is how I post the two values to server using postman.
How should I write in http?
var url = "xxx";
var response = await http.post(url, headers: headers, body: {
....
'all_receivers': adminList.toString(),
'commence_time': endTime, // this no issue
...
});
I pass adminList which is [725,607], but get error:
Error
all_receivers id [725 is invalid. all_receivers id 607] is invalid.
You create a json and pass it
or
You can create and array of strings
You can simply resolve that by casting your List to String.
By casting the token list using toString() method you will get a String like this "['token1','token2']"
Here's the modified code:
List<String> adminList=["725","607"]; // how to pass 725,607
var response = await http.post(url, headers: headers, body: {
'all_receivers': adminList.toString(), // how to pass 725,607
}
try to pass with jsonEncode
var response = await http.post(url, headers: headers, body: JsonEncode({
'all_receivers': adminList,
});
print(response);
This is how I fixed
final receivers = adminList.join(",");
final body = {'all_receivers':receivers}
http.post(url', body: body);

Invalid Header Name In Flutter HTTP Request

I have a login page where i am trying to send a login request to my backend. But I get an Unhandled Exception: Invalid header field name. Here is my submit function
submit() async {
var res = await LoginAPI().loginData(
{'email': _emailController.value, 'password': _passwordController.value});
var body = json.decode(res.body);
print(body);
}
Then in my LoginAPI class here is my loginData function that makes the call to the backend
import 'dart:convert';
import 'package:http/http.dart' as http;
class LoginAPI {
final String _url = "http://10.0.2.2:8000/api/";
Map<String, String> headers = {"Content-type": "application/json"};
loginData(data) async {
var fullUrl = _url + "v1/users/login";
return await http.post(
fullUrl,
body: jsonEncode(data),
headers: headers
);
}
}
Here is my request through postman
Here is my response through postman
When I make the same request with Postman i get the response I am supposed to get. What Am i doing wrong?
try this
Map<String, String> headers = {"Content-type": "application/json", "Accept": "application/json",};
It looks from your postman request that you are just sending form data (not a json encoded body). package:http will form encode the body for you (and add the content type header) if you do the following:
return await http.post(
fullUrl,
body: data,
);
So i was able to solve the issue. The issue was with my CORS middleware on my server. I just made some changes and it worked fine. So if anyone has this issue just know it has nothing to do with flutter but most probably CORS