How to handle cors for web flutter - flutter

I have been struggle to fix the cors problem in my PWA project of flutter and I am following this
how to solve flutter CERTIFICATE_VERIFY_FAILED error while performing a POST request?.
I am using universal_io package since dart.io can not be used for web...here is the part of the code
HttpClient client = new HttpClient();
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
String url = 'https:xxxx.php';
Map map = {
"a": "a",
"b": "b"
};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
if (request is BrowserHttpClientRequest) {
request.credentialsMode = BrowserHttpClientCredentialsMode.include;
}
HttpClientResponse response = await request.close();
print(response.toString());
String reply = await response.transform(utf8.decoder).join();
print(reply);
but I get the error that say like this
--------------------------------------------------------------------------------
BrowserHttpClient received an error from XMLHttpRequest (which doesn't tell
reason for the error).
HTTP method: POST
URL: https://www.rscm.co.id/apirscm/v2.php
Origin: http://localhost:64121
Cross-origin request!
XmlHttpRequest 'credentials mode' is enabled.
Did the server send the following mandatory headers?
* Access-Control-Allow-Credentials: true
* Access-Control-Allow-Origin: http://localhost:64121
* In credentials mode, '*' would fail!
* Access-Control-Allow-Methods: POST
is there a way to solve this problem?

You can you local host server in the debug mode of chrome, here is how:
open this in terminal.
open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/Users/i0868/Desktop/Chrome" --disable-web-security

you can do something like thisto enable credentials mode:
final httpClientRequest = MyHttpClientRequest;
if (httpClientRequest is BrowserHttpClientRequest) {
httpClientRequest.credentialsMode = BrowserHttpClientCredentialsMode.include;
}
But prefer using this librairy universal_io instead of dart.io

Related

Flutter http 400 error when sending an XFile Image

I want to send a jpg file from my flutter app to .Net backend. I'm using http package.
My code is as follows:
var uri = Uri.parse('$url/upload/$id');
var request = http.MultipartRequest('POST', uri);
var headers = {'accept': '*/*', 'Content-Type': 'multipart/form-data'};
request.headers.addAll(headers);
var x = await file.readAsBytes();
var mFile = http.MultipartFile.fromBytes('file', x);
request.files.add(mFile);
var response = await request.send();
Here file is an XFile file from package cross_file.
Unfortunately I get an error code - 400 "Bad request".
On the backend side code looks as follows
[HttpPost("/upload/{id}")]
public IActionResult UploadImage(IFormFile imageFormFile, [FromRoute] Guid id)
{
// program does not even enter the function
}
I've tested this using Swagger and it works, it generates following curl:
curl -X 'POST' \
'http://localhost:44383/apiname/f7765448-be93-4e72-b62e-04623b4ccdb1' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'imageFormFile=#sample.jpg;type=image/jpeg'
I've searched some forums and tutorials, but nothing works.
I've tried adding the file using fromBytes, fromPath and fromString, none worked.
I've tried experimenting with different combinations of headers and fields, this didn't work either. In particular I've tried to add fields "imageFormFile" and "type", as in Swagger curl, but it didn't work as well.
I've also tried to rewrite this using dio, but got the same result (also I'd rather stick to http, as the rest of my project uses it).
Future uploadRequest(String url, String filePath) async {
final dio = Dio();
dio.options.contentType = "multipart/form-data";
final multiPartFile = await MultipartFile.fromFile(
filePath,
filename: filePath.split('/').last,
);
FormData formData = FormData.fromMap({
"file": multiPartFile,
});
final response = await dio.post(
url,
data: formData,
);
return response.data;
}
This is 100% working solution but with dio package as I prefer it over http. But It doesn't mean that with http it is impossible.
IMPORTANT: formData could be different according to your API

Dio dart/Flutter get and set cookie

I would like to do a set cookies, do a get request and after get the cookies.
In python it will be this:
> import requests cookies = {'status': 'working','color':'blue'}
> response = session.get('https://google.com/', cookies=cookies)
> print(session.cookies.get_dict())
Do you know how to flutter it? I tried something like this but it doesn't seem to have a cookie in the response and the cookie doesn't seem to be sent
Map<String, String> headers = {
"status":"working",
"color":"blue"
};
final BaseOptions dioBaseOptions = BaseOptions(
baseUrl: 'https://google.com',
headers: {
'Cookie': headers,
},
);
dio = Dio(dioBaseOptions);
var cookieJar=CookieJar();
dio.interceptors.add(CookieManager(cookieJar));
var response = await dio.get('https://google.com/');
Cookie is set by a server in a response header and a browser sends it back in a request header.
After receiving an HTTP request, a server can send one or more Set-Cookie headers with the response. The browser usually stores the cookie and sends it with requests made to the same server inside a Cookie HTTP header.
See Using HTTP cookies for details.
CookieManager does this for dio and Flutter.
To access Cookies in a dio response
final cookies = response.headers['set-cookie']

How to create a Postman server mock for uploading file and doing some uploading test of Flutter code?

I'm trying to connect to a printer server to be able to save the printing files directly in the printer storage. I'm able to do it using the curl
curl -v -H 'Content-Type:application/octet-stream' 'http://192.168.1.125/upload?X-Filename=model.gcode' --data-binary #model.gcode
Now I'm trying to add this function to a Flutter app but don't works....
So now I am trying to debug the code using a postman server.
Can you help me to create a postman server mock to upload the file as binary, like in this curl code?
curl -v -H 'Content-Type:application/octet-stream' 'http://192.168.1.125/upload?X-Filename=model.gcode' --data-binary #model.gcode
I want to create it because I want to test this Flutter code witch isn't working in the server of the printer.
FLUTTER CODE:
Future<void> uploadFile(File file) async {
///Using HTTP Package
Map<String, String> headers = {
"Content-type": "application/octet-stream",
};
var stream = new http.ByteStream(DelegatingStream.typed(file.openRead()));
var length = await file.length();
var uri = Uri.parse("http://192.168.1.125/upload?X-Filename=nupo.gcode");
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('application', stream, length,
filename: file.path);
request.headers.addAll(headers);
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
The server should be able to receive binary file and the command should be upload?X-Filename=filename.gcode, X-Filename is the command to give the name.
(this files are 3D printing files so .gcode is the enstention of motor command)
Postman is not a server usable for this scope. You can use it only for testing an existing server. Best practice with postman or visiti [POstman support][1]

problem with flutter and post http request for authentication with nginx server with flask

I'm testen with writing an rest-api in Flask in combination with a mobile flutter client.
I have a problem with authentication wiht Flask-JWT.
I use ngnix and uwsgi to run the flask application on ubuntu 20.04.
With debug mode of the flask app, it runs without without problems.
With Postman it works always.
Flutter dart code:
Future<String> authRequest() async {
try {
final HttpClient client = HttpClient();
client.badCertificateCallback =
((X509Certificate cert, String host, int port) =>
true); // accept all certificat
final Map login = {
"username": "user",
"password": "goodsecret",
};
final request = await client.postUrl(Uri.parse(ProviderBase.url + '/auth'));
request.headers.add(HttpHeaders.contentTypeHeader, "application/json");
request.add(utf8.encode(json.encode(login)));
final response = await request.close();
final reply = await response.transform(utf8.decoder).join();
final jresponse = json.decode(reply);
ProviderBase.authtoken = jresponse['access_token'];
print('token: ${ProviderBase.authtoken}');
} catch (error) {
print('Error: ${error.toString()}');
}
}
I get this error message (response) in flutter:
"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not understand.</p>"
Maybe someone has an idea?
I uses at the moment self signed certificate.
I found the solution:
it's the missing header content length. With the webserver it's necessary.
this works for me:
...
final body = utf8.encode(json.encode(login));
request.headers.add(HttpHeaders.contentTypeHeader, "application/json");
request.headers.add(HttpHeaders.contentLengthHeader, body.length.toString());
request.add(body);
...

How i can get Token from headers?

I did authorization via http. post, send a JSON Body with username and password, in the response I get a Header, the Header has a token, it is stored in 'set_cookie: Authorization=token', how do I get it and write it to the storage?
You can get the cookie from the response of login request using the following code
HttpClient _httpClient = new HttpClient();
HttpClientRequest request = await _httpClient.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
print(response.cookies); // this is a List<Cookie>, you can iterate and find the required cookie
Now you can store the cookie using shared_preference plugin, and use it in your all the future requests.
HttpClient client = new HttpClient();
HttpClientRequest clientRequest =
await client.getUrl(Uri.parse("http: //www.example.com/"));
clientRequest.cookies.add(Cookie("sessionid", "asdasdasqqwd"));
You can also explore dio library and use AuthInterceptor to add the token for all the requests for you.