How to put raw data in a http get request in Flutter(Dart)? - flutter

I'm trying to execute the following curl in dart but I can't find a way to achieve that:
curl --location --request GET 'https://someurl.com/query' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer xxxx' \
--data-raw '{
"query":"test_value",
"size":10
}'
The only way I've found to achieve this is to use POST and put the raw data inside the body but I was wondering if there is a real way to achieve that since the POST request with a body seems to be about 220ms slower than the GET one(I know that they should be almost equal, it may be something from the server when recieving the request).

The default get() method of the http package doesn't allow you to add data since that isn't a common thing to do. You can get around this by using the Request object directly for more fine-grained control, as stated in the docs:
Request req = Request('GET', Uri.parse('https://someurl.com/query'))
..body = json.encode(data)
..headers.addAll({
"Content-type": "application/json",
"Authorization": "Bearer xxxx"
});
var response await req.send();
if (response.statusCode == 200) {
// do something with valid response
}
I'd look at getting the POST variant working properly, since a GET method semantically shouldn't do anything with the provided body. But that's a different discussion of course.

import 'package:http/http.dart' as http;
// Define the raw data to be sent in the request
String rawData = '{ "key": "value" }';
// Send the GET request with the raw data as the body
http.Response response = await http.get(
'https://example.com/endpoint',
headers: {'Content-Type': 'application/json'},
body: rawData,
);
// Check the status code of the response to see if the request was successful
if (response.statusCode == 200) {
// The request was successful, process the response
} else {
// The request was not successful, handle the error
}

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

Flutter receives 422 response from Fastapi when posting a PNG file

I have created a working localhost API with FastAPI. The POST takes a PNG, does some image processing and returns a PNG as expected when I click the 'try it out' button in the FastAPI generated docs:
The curl post command shows as follows:
curl -X 'POST' \
'http://localhost:8345/api/predict' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#test_img.png;type=image/png'
The image File is successfully retrieved from the image picker library. (Where the image1 object has been initialized as File image1; in the app page's class.
Future getImage() async {
var imageTmp = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
image1 = imageTmp;
print('Image Path $image1');
});
}
I tried to emulate the API call with the below function in Flutter.
doUpload() {
/*
curl -X 'POST' \
'http://192.168.178.26:8345/api/predict' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#test_img.png;type=image/png'
*/
var request = http.MultipartRequest(
'POST',
Uri.parse("http://<my locally hosted ip>:8345/api/predict"),
);
Map<String, String> headers = {"Content-type": "multipart/form-data"};
request.files.add(
http.MultipartFile(
'image',
image1.readAsBytes().asStream(),
image1.lengthSync(),
filename: 'filename',
contentType: MediaType('image', 'png'),
),
);
request.headers.addAll(headers);
print("request: " + request.toString());
request.send().then((value) => print(value.statusCode));
}
When I run the doUpload() function, a POST is successfully sent to the localhost API, but it returns a 422 error 'unprocessable entity'.
What I tried:
I tried to set the image type in doUpload to jpg, jpeg, but I keep getting a 422 error.
I tried looking up where the image_picker is supposed to store the temporary file to see if it's stored correctly, but when I look at the generated filepath, I don't see the actual file and tmp folder:
filepath: File: '/data/user/0/<my package name>/cache/image_picker3300408791299772729jpg'
looking at my local UI filepath, I see:
It shows no folder named cache, so I can't inspect it like this. However, the image picker saves it with a jpg at the end (not .jpg, is this normal?)
I also tried adding this debugger function to my fastAPI server.py, but I'm not sure how I can inspect the resulting data in the current flutter code:
https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body
The resulting value has properties like statusCode and reason, but I don't see a full json output option.
To mimic that curl command exactly, use this: (I've used the convenience constructor for simplicity)
final request = http.MultipartRequest(
'POST',
Uri.parse('http://<my locally hosted ip>:8345/api/predict'),
);
request.files.add(
await http.MultipartFile.fromPath(
'file', // NOTE - this value must match the 'file=' at the start of -F
image1.path,
contentType: MediaType('image', 'png'),
),
);
final response = await http.Response.fromStream(await request.send());
print(response.body);

what is the correct way to pass Bearer token in header section of my HTTP.Post in flutter

My Post API need a customer_id in body but also need a bearer token. I am passing it using following code
var myId="1005",
var token="my Token here"
var response = await http.post(Uri.parse("http://haulers.tech/jashn/mobile/home/shoutouttype"),
body: ({
"customer_id":myId.toString,
}),
headers: ({
"Authorisation": token.toString, //here I want to pass Bearer Token
})
);
This code return status code 401.
Pay attention to the word Bearer its must be Capitalized other ways it wont work, not sure whats the reason, but for flutter http calls make sure to capitalize that word like this
var response = await httpClient.post(
url,
headers:{
"Accept": "application/json",
"Content-type": "application/json",
"Authorization": "Bearer $token"
},
body :{some body});
Bearer tokens are usually sent preceded with Bearer : the following key value pair:-
"Authorization": "Bearer {TOKEN}"
Should work.

The argument type 'Set<String>' can't be assigned to the parameter type 'Map<String, String>'

I'm trying to create an user authentication system using Auth0 in my Flutter app. The Auth0 REST documentation gave an example of cURL but I didn't find any flutter package which does the job of cURL. So, I used http.
Here's the code:
Future<String> getToken(String userId) async {
final response = await http.post(
Uri.parse('https://my-auth0-subdomain.auth0.com/oauth/token'), // I used my real subdomain
body: jsonEncode({
'grant_type=client_credentials',
'client_id=my_project_client_id', // I used my real client id
'client_secret=my_project_client_secret', // I used my real client secret
'audience=https://my-auth0-subdomain.auth0.com/api/v2/' // I used my real subdomain
}),
headers: {
'content-type: application/x-www-form-urlencoded'
},
);
final token = jsonDecode(response.body)["access_token"];
return token;
}
This gives me an error that The argument type 'Set<String>' can't be assigned to the parameter type 'Map<String, String>'. on line 10 (headers: {...}). I can resolve this error by using headers: {'content-type': 'application/x-www-form-urlencoded'},.
But this then gives the error from Auth0 {"error":"access_denied","error_description":"Unauthorized"}. The API is set up properly, because on running
curl --request POST \
--url 'https://my-auth0-subdomain.auth0.com/oauth/token' \
--header "content-type: application/x-www-form-urlencoded" \
--data grant_type=client_credentials \
--data 'client_id=my_project_client_id' \
--data client_secret=my_project_client_secret \
--data 'audience=https://my-auth0-subdomain.auth0.com/api/v2/'
it returns a "access_token", "scope", "expires_in" and "token_type".
Please help. It's very important.
Thanks in advance :)
Try to send data as url encoded using :
Map<String, String> myBody= {
'grant_type' : 'client_credentials',
'client_id' : 'my_project_client_id', // I used my real client id
'client_secret' : 'my_project_client_secret', // I used my real client secret
'audience ' : 'https://my-auth0-subdomain.auth0.com/api/v2/' // I used my real subdomain
};
Future<String> getToken(String userId) async {
final response = await http.post(
Uri.parse('https://my-auth0-subdomain.auth0.com/oauth/token'), // I used my real subdomain
body: myBody,
headers: {
'content-type: application/x-www-form-urlencoded'
},
);
final token = jsonDecode(response.body)["access_token"];
return token;
}

Uber API: Endpoint requests returns Not supported in sandbox environment

I have successfully completed the first three steps of the authentication process: step one(authorize), step two (receive redirect ) and step three (get an access token).
But, doing the following request gives me an error:
curl -H 'Authorization: Bearer xxxxoKnAKxxxxxndQNRZgRa0Dxxxxx' 'https://sandbox-api.uber.com/v1/requests'
Response:
{"message":"Not supported","code":"not_found"}
I have the same message with all required params:
curl -H 'Authorization: Bearer xxxxoKnAKxxxxxndQNRZgRa0Dxxxxx' 'https://sandbox-api.uber.com/v1/requests?product_id=5b451799-a7c3-480e-8720-891f2b51abb4&start_latitude=48.869576&start_longitude=2.30825&end_latitude=48.84839&end_longitude=2.395921'
Am I missing something?
Edit:
Ruby version with HTTParty:
def request(bearer, product_id="5b451799-a7c3-480e-8720-891f2b51abb4", start_latitude=48.869576, start_longitude=2.30825, end_latitude=48.84839, end_longitude=2.395921)
parameters = { product_id: product_id,
start_latitude: start_latitude,
start_longitude: start_longitude,
end_latitude: end_latitude,
end_longitude: end_longitude
}
self.class.post('/v1/requests', query: parameters, headers: { "Authorization" => "Bearer #{bearer}", 'Content-Type' => 'application/json' })
end
A GET to 'https://sandbox-api.uber.com/v1/requests' won't work since you need to include a such as https://sandbox-api.uber.com/v1/requests/request_id
A POST to 'https://sandbox-api.uber.com/v1/requests' requires you to post the parameters as part of the JSON body.
Once you have the request ID as part of the response, you will able poll for details using the first command.