http package can not convert map to query URL in flutter - http

I am trying make an http post request with the method below. when I run the method I keep getting the message that an exeption has occured and am being pointed to this utils.dart file. From what am seeing my best guess is that there is a problem converting the map data I have provided in the url into the query string. Icant seem to find what am doing wrong tho.How may I solve this.
Request Method
Future<List>getdata()async{
print("Loading ....");
String theUrl ="https://http://127.0.0.1/codeishweb/notifiedUser.php";
var res = await http.post(Uri.encodeFull(theUrl),headers: {"Accept":"application/json"},body: {"notID":2},);
var responseBody = json.decode(res.body);
print("results ::$responseBody");
//print("the response at position something::::\nHeading\n${responseBody[0][7]['post_head']}\nBody\n${responseBody[0][7]['post_body']}");
return responseBody;
}
Error message in utils.dart
/// Converts a [Map] from parameter names to values to a URL query string.
///
/// mapToQuery({"foo": "bar", "baz": "bang"});
/// //=> "foo=bar&baz=bang"
String mapToQuery(Map<String, String> map, {Encoding encoding}) {
var pairs = <List<String>>[];
map.forEach((key, value) => pairs.add([
Uri.encodeQueryComponent(key, encoding: encoding),
Uri.encodeQueryComponent(value, encoding: encoding)
]));
return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}

Related

salesforce: Absolute path in the request URI

Trying to apply abs_path from RFC2616 (https://www.rfc-editor.org/rfc/rfc2616#section-5.1.2) but receiving callout exception 'System.CalloutException: no protocol: /animals'.
End point url trying in following example : http://th-apex-http-callout.herokuapp.com/animals
eg.
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setHeader('Host','th-apex-http-callout.herokuapp.com');
request.setEndpoint('/animals');
request.setMethod('GET');
HttpResponse response = http.send(request);
// If the request is successful, parse the JSON response.
if (response.getStatusCode() == 200) {
// Deserializes the JSON string into collections of primitive data types.
Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
// Cast the values in the 'animals' key as a list
List<Object> animals = (List<Object>) results.get('animals');
System.debug('Received the following animals:');
for (Object animal: animals) {
System.debug(animal);
}
}
expected output :
Received the following animals:
majestic badger
fluffy bunny
etc...
I've never tried sending Host as a header but this works just fine
request.setEndpoint('http://th-apex-http-callout.herokuapp.com/animals');

Flutter : InternalError , Filter error, bad data when upload image on server

I do simple upload image to server using http packages. But the problem is , when i upload it i got error Unhandled Exception: InternalError: 'Filter error, bad data'.
Upload
Future testUpload(File selfieImage, String pembertang) async {
final result = await reusableRequestServer.requestServer(() async {
//create multipart request for POST or PATCH method
var request = http.MultipartRequest('POST', Uri.parse('$baseApiUtang/addUtang'));
//add text fields
request.fields['pembertang'] = '$pembertang';
//create multipart using filepath, string or bytes
var pic = await http.MultipartFile.fromPath('selfie', selfieImage.path);
//add multipart to request
request.files.add(pic);
var response = await request.send();
//Get the response from the server
var responseData = await response.stream.toBytes();
var responseString = String.fromCharCodes(responseData);
print('responseData : $responseData');
print('responseString : $responseString');
return responseString;
});
return result;
}
With this strange problem , i try it with postman but it's work like i want.
My opinion, it's not problem in my backend code. I missed something ?
Update
Similiar problem with me on this issue
Update 2
When i look inside the code and print variable 1 by 1, i got status code 403
Hi can you pls try following code
var stream = new http.ByteStream(Stream.castFrom(imageFile.openRead()));
// get file length
var length = await imageFile.length();
// create multipart request
var request = new http.MultipartRequest("POST", uri);
var name = firstname +"."+imageFile.path.split(".").last;
// multipart that takes file
var multipartFile = new http.MultipartFile('profile', stream, length,
filename: basename(name));
In my case my can not take so much long name so i customise image name and then tried and its working .
so you can also try this.

Dart - sending GET parameters that are lists

I want to send parameters with an http GET request in dart. The first answer here demonstrates it well: How do you add query parameters to a Dart http request?
var uri =
Uri.https('www.myurl.com', '/api/query', queryParameters);
However, a major problem is that queryParameters only accepts:
Map<String, String>
This doesn't allow me to pass in lists/arrays.
If i change my get request to a post request, I am easily able to send a
body (as a json encoded String) as outlined by the flutter docs: https://pub.dev/documentation/http/latest/http/post.html
post(url, {Map<String, String> headers, body, Encoding encoding})
However, the get request has no such equivalent argument for query parameters: https://pub.dev/documentation/http/latest/http/get.html
get(url, {Map<String, String> headers})
I have also tried adding query parameters directly to the url like so:
get('www.myurl.com/api/query/?array[]=value1&array[]=value2&array[]=value3)
but the square brackets [] always get transformed into %5B%5D when I receive it in the server.
Any help is appreciated.
Thanks
In fact, queryParameter takes Map<String, dynamic>. Check the source code:
factory Uri(
{String scheme,
String userInfo,
String host,
int port,
String path,
Iterable<String> pathSegments,
String query,
Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
String fragment}) = _Uri;
The dynamic can be either a String or an Iterable<String>. So,
var uri = Uri(
scheme: 'http',
host: 'www.myurl.com',
path: '/api/query/',
queryParameters: {
'array': ['value1', 'value2', 'value3'],
},
);
print(uri);
prints:
http://www.myurl.com/api/query/?array=value1&array=value2&array=value3

Http.put does not accept any but a String

Simple is, that I am trying to make a PUT request to my API but I get the type error of:
_CastError (type 'List<String>' is not a subtype of type 'String' in type cast)
My API accepts an Array of strings (string[]), which I know work because I am currently consuming it on the sibling web platform. So I am trying to replicate that on the Flutter app with the below code. At the moment it is just static code.
I know, that the http module is only accept string but is there a way to get around this? As it does not make sense, as what happens if we want to post an int, bool or <List<String>>. I know you can obviously convert using .toString() but my API has certain validation and is rigid on what it can accept.
Code below:
When I use this payload it works because it follows the rigid types of the Http module (<String, String>)
Map<String, String> payloadThatWorks = {"first_name": "First Name"};
Now when I want to give the payload of the type Map<String, List<String>> with the code below:
Map<String, List<String>> payload = {
"personal_settings": ["allow-notification-discussion-mentions"]
};
It throws the error of _CastError (type 'List<String>' is not a subtype of type 'String' in type cast)
in the http.put function below:
Main API Helper function
static Future<http.Response> queryPut(String apiPath, {dynamic body}) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String accessToken = prefs.getString('access_token');
var response = await http.put(
Uri.encodeFull(_urlBase + '$apiPath'),
body: body,
headers: {
HttpHeaders.authorizationHeader: "Bearer $accessToken",
'Accept': 'application/json'
},
);
return response;
}
However, when helper function is called in my Widget...
http.Response response =
await ApiService.queryPut('/api/users/$username', body: payload);
So i'm in a spot where the http module does not accept anything put <String> but the API does not accept anything but an Array or <List<String>>
How can I get round this or understand why the http put method is so rigid?
Thank you in advance :)
Sam
You can import dart:convert and use its jsonEncode to convert your map or array of map into a string
So basically you will have to do the following
String payloadStr = jsonEncode(payload)
and use this payloadStr to pass in the http methods. Similarly you can use JsonDecoder to convert json string to Map or Array of map.

Retrieve the single value from webapi by using Angular

Goal: retrieve the single value "test" in Angular.
Problem: I get an error message
Error: SyntaxError: Unexpected token e in JSON at position 1 at JSON.parse ()
What syntax am I missing?
ASP.NET
// https://localhost:44353/api/Jobadvertisement/VVValidate/4
[HttpGet("VVValidate/{id:int}")]
public ActionResult<String> VVValidate(int id)
{
return "test";
}
Angular
const url = environment.url
let asdfasdf2 = url + 'api/Jobadvertisement/VVValidate/' + "4";
var dsfsdssf = this.http.get(asdfasdf2).subscribe(data => {
console.log(data);
});
Can you please try using httpOptions in Angular with something like this:
const url = environment.url;
let asdfasdf2 = url + 'api/Jobadvertisement/VVValidate/' + "4";
var dsfsdssf = this.http.get(asdfasdf2, { responseType: 'text' }).subscribe(data => { console.log(data); });
You need to change ActionResult to string:
[HttpGet("VVValidate/{id:int}")]
public string VVValidate(int id)
{
return "test";
}
Angular's HttpClient expects JSON data per default, which is why you get a JSON deserialization error upon returning plain text from your API.
You need to pass responseType: 'text' as option to the get method, in order to prevent HttpClient from treating your data as JSON:
httpClient.get("url", { responseType: 'text' });
You can find more information regarding this in Angular's Documentation.
Even though your API code works as it is, I'd like to point out two things:
You can unwrap your String and remove the ActionResult, as it is not needed.
I would encourage you to use the string type instead of System.String. For a detailed explanation, please refer to this.
Your code would look like this after applying these changes:
[HttpGet("VVValidate/{id:int}")]
public string VVValidate(int id)
{
return "test";
}

Resources