I doing a Flutter app and I using dio to connect app with my web service.
When I want to access to custom headers in response, on mobile I don't have any problem, but this headers on web not be available and get different.
My code:
final dio = Dio();
final response = await dio.getUri(requestUri,
options: Options(headers: {
'authorization': 'Bearer ${credentials!.accessToken}',
}));
How I do to on web and mobile get a same custom headers?
This is due to CORS, part of the browser built-in cross-site security restrictions. Your server need to include your custom headers into the "preflight" OPTIONS response header Access-Control-Expose-Headers to allow your browser to see those headers.
For example, https://discuss.istio.io/t/configuring-cors/7458/5
Related
So im currently trying to send images from file picker to an api that had a file input, here is the postman display and the thing was, i've tried it with numerous way that was in other post, but none of them is working for me, this is the error that i get from my web browser console and this is the code that i've tried to work with:
var postUri = Uri.parse(constanta.getMyid());
http.MultipartRequest request = new http.MultipartRequest("POST", postUri);
http.MultipartFile multipartFile = await http.MultipartFile.fromBytes(
'data', image);
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
print(response.statusCode);
i don't think the main problem was the CORS, because the api log is indicating that the request is received, but no file was attached to that request.
additional note : i've tried everything from the client side, and i cannot open/edit the backend, because it's a third party api (not owned by me).
As I can see your errors main problem here first is data was rejected from your Server as the server not allowing you to upload files and throw Cross-Origin Access which you have to solve first and then you should try.
If your postman is able to upload images on server that is because postmen itself capable of solving Cross-Origin Acess Error, so here is the solution for the node.js
If your backend is in node js you can inject the below code into your middleware.
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'XMLHttpRequest,Origin,X-Requested-With,Content-Type,Accept,Authorization');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT,POST,PATCH,DELETE,GET');
return res.status(200).json({});
}
next();
});
Or you can use localhost as a backend server.
I'm using package:dio in a Flutter web application.
Whenever I send a POST request, however, it gets changed into an OPTIONS request. The function that makes the API request looks like this:
Future<LoginResponse> login(LoginRequest request) async {
final dio = Dio(BaseOptions(baseUrl: "http://localhost:8000"));
final response = await dio.post("/login", data: request.toJson());
return LoginResponse.fromJson(jsonDecode(response.data));
}
This code sends an OPTIONS request to http://localhost:8000/login. If I add that endpoint to my server, it works.
If I send the POST request from postman manually it also works.
If I change this code to other methods (e.g. dio.delete(...)) it also maps to an OPTIONS request.
Why is dio rewriting my requests?
The Flutter Web application send a HTTP REST API POST request and gets back a JSON response and a cookie in the Set-Cookie header as follows.
(Flutter (Channel beta, 1.22.0, on Microsoft Windows)
When the cookie is extracted, the response does not seem find the header value. The call and extraction code is:
var response = await http.post(url, headers: {"Content-Type": "application/json"}, body: jsonEncode(data));
if (response.statusCode == 200) {
var cookie = response.headers['set-cookie'];
print('cookie: $cookie');
}
The console result is:
cookie: null
The server side runs on ASPNet.Core 3.1 in a Docker container, however it should not be an issue, since the cookie is there in the header. So, how can I extract it in Flutter Web?
Actually my final goal is to send the cookie back with every other request. But it does not seem to happen automatically in the browser. So it is also a good solution if someone could point out the proper way of handling this scenario.
Any help is appretiated. Thanks.
The question was asked a month ago but my answer might be helpful for someone else.
Cookies in Flutter Web are managed by browser - they are automatically added to requests (to Cookie header), if the cookie was set by Set-Cookie previously - more precisely, it works correctly when you do release build.
In my case it didn't work during dev builds. My solution:
On server set headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:61656
// port number may be different
In flutter:
class member:
final http.Client _client = http.Client();
// example
Future<String> getTestString() async {
if (_client is BrowserClient)
(_client as BrowserClient).withCredentials = true;
await _client.get('https://localhost/api/login');
await _client.get('https://localhost/api/login');
return 'blah';
}
http.Client() creates an IOClient if dart:io is available and a BrowserClient if
dart:html is available - in Flutter Web dart:html is available.
Setting withCredentials to true makes cookies work.
Run your app:
flutter run -d chrome --web-port=61656
// the same port number that on server
Remember that in Flutter Web network requests are made with browser XMLHttpRequest.
Im trying to consume TomTom maps api to get the location .
My function :
getLocationAddress(lat: number, lon: number) {
const url = `${baseUrl}search/${versionNumber}/reverseGeocode/${lat},${lon}.json/?key=${apiKey}`;
const headers = new HttpHeaders({
"Content-type": "application/json",
"Access-Control-Allow-Methods": "GET,OPTIONS,POST",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"Access-Control-Allow-Headers,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Authorization,Content-Type",
});
const observable = this.http.get(url, { headers: headers });
return observable;
}
The url is correct and i have provided the headers as above . I cant get past this error:
Access to XMLHttpRequest at <url> has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response
TomTom is a 3rd party api server . The is routed to the correct location and i can see the response from the server on the browser when pasting the link in a new window
Based on the error message it appears your headers are misconfigured, specifically the "authorization" header attribute.
You may want to use their SDK and/or JS libraries, at it will set the headers for you.
You need to provide an API key, otherwise CORS policy will reject the requests, as shown in their examples https://developer.tomtom.com/maps-sdk-web-js/functional-examples#examples,code,vector-map.html
In API they call without Authorization is fine.
How to set header for it?
"thanks"
let headers: Headers = new Headers({ 'Authorization': token, 'Content-Type': 'application/json; charset=UTF-8' });`
let options: RequestOptions = new RequestOptions({headers: headers});
let params: URLSearchParams = new URLSearchParams();
params.append('latitude', '23.259933');
params.append('longitude', '77.412615');
params.append('nearby', '5');
return this.http.post(baseUrl, params, options)
.map(
(response: Response)=>{
return response;
}
)
Chrome console:
Response for preflight has invalid HTTP status code 404
This happens because the browser sends the headers of your request to the server before sending the actual request (what is called preflight) so as to verify your request complies with the CORS policy that is defined in the server's configuration.
So what you need to do is double check that the server you are contacting is configured properly to accept the request as you make it.
Make sure that your backend server is accepting not only the POST request but also an OPTIONS request for the same endpoint url. The OPTIONS request should just return with the success 200 code.
On that server you probably have something like "when a user hits endpoint /abc with request type POST, then return some data". You also need something that says "when a user hits endpoint /abc with request type OPTIONS return 200 OK"
If all else fails you could try using this plugin in your browser, but keep in mind this will help only continuing development and is a band-aid solution that won't work in production of course.