I want to send a GET http request with parameters, my problem is that when I add the parameters in the request URL manually it works fine, but when I pass them as parameters it returns an exception without any explanation and somehow the execution stops after Uri.https
here is the code that I want to achieve
Future<List<LawFirm>> getLawFirms () async {
Map<String, dynamic> parameters = {
'total': true
};
final uri =
Uri.http('www.vision.thefuturevision.com:5000',
'/api/law-firm', parameters);
final response = await http.get(uri);
var dynamicResponse = jsonDecode(response.body);
totaLawFirms = await dynamicResponse['total'];
var lawFirms = await dynamicResponse['data'];
List<LawFirm> list = List<LawFirm>.from(lawFirms.map((x) => LawFirm.fromJson(x)));
print(list);
notifyListeners();
return list;
}
and here is the manual way which shouldn't be applied
final response = await get(Uri.parse('$baseURL/law-firm?total=true'));
I have also tried the dio library from pub.dev but also wasn't helpful.
And finally thanks in advance to everyone
You may try this
Map<String, dynamic> parameters = {
'total': true
};
var uri = Uri(
scheme: 'http',
host: 'www.vision.thefuturevision.com:5000',
path: '/law-firm',
queryParameters: parameters,
);
final response = await http.get(uri);
import 'package:http/http.dart' as http;
final response =
await http.get(Uri.parse("${Constants.baseUrl}endpoint/param1/param2"));
Just modify your GET request like this.
Try this
import 'package:http/http.dart' as http;
callAPI() async {
String login = "sunrule";
String pwd = "api";
Uri url = Uri.parse(
"http://vijayhomeservices.in/app/api/index.php?apicall=login&login=$login&password=$pwd");
final response = await http.get(url);
if (response.statusCode == 200) {
final body = json.decode(response.body);
print(body.toString());
} else {
throw Exception("Server Error !");
}
}
Query parameters don't support bool type. Use String instead: 'true'.
A value in the map must be either a string, or an Iterable of strings, where the latter corresponds to multiple values for the same key.
Map<String, dynamic> parameters = {'total': 'true'};
final uri = Uri.http(
'www.vision.thefuturevision.com:5000', '/api/law-firm', parameters);
print(uri); // http://www.vision.thefuturevision.com:5000/api/law-firm?total=true
See Uri constructor for details.
Related
I'm having issues with the return type of this HTTP request, I need to return Future<List> but the map is returning a List<Future>. I don't know how to get the CustomerInfo without it being a future and I don't know how to return it any other way.
if (response.statusCode == 200) {
Iterable l = json.decode(response.body);
final data = List.from(l.map((model) async {
final name = model['UserName'];
final id = model['UserICode'];
return {name, id};
}));
final users = data.map<CustomerInfo>((e) async {return await getFaxinfo(e.id, e.name);});
return users;
} else {
throw 'err';
}
}
Future<CustomerInfo> getFaxinfo(
String id,
String name,
) async {
final baseUrl = 'localhost';
final int port = 3003;
final accountsPath = '/accounts';
final accountsFaxInfoPath = '$accountsPath/fax-info';
final Map<String, dynamic> queryParam = {'id': id};
final uri = Uri(
scheme: 'http',
path: accountsFaxInfoPath,
host: baseUrl,
queryParameters: queryParam);
final response = await http.get(uri);
return CustomerInfo(sent: 200, received: 300, name: 'Test');
}
The problem is that an async function always returns a Future no matter if you call await inside it or not. To fix it a good approach is to use list comprehension. A simple for loop also would do.
Instead of those 2 maps that result in List<Future>:
final data = List.from(l.map((model) async {
final name = model['UserName'];
final id = model['UserICode'];
return {name, id};
}));
final users = data.map<CustomerInfo>((e) async {return await getFaxinfo(e.id, e.name);});
Do the following with list comprehension:
final users = [
for (final model in l)
await getFaxinfo(model['UserICode'], model['UserName'])
];
Now if you want to make the HTTP calls in parallel it's possible to do a Future.wait() in a List<Future> to get the result as List<CustomerInfo>. Something like the following:
final users = await Future.wait(l.map((model) async =>
await getFaxinfo(model['UserICode'], model['UserName'])));
I am getting an error in the url part of the code, I have shown the error in the screenshot. How can I fix my code without changing its function.
Future<List<Articles>?> getNews() async {
String url = "https://jsonplaceholder.typicode.com/posts";
final response = await http.get(url);
if (response.body.isEmpty) {
final responseJson = json.decode(response.body);
News news = News.fromJson(responseJson);
return news.articles;
}
return null;}
You need to pass Uri instead of string.
final response = await http.get(Uri.parse(url));
You can assign uri something like this
var uri= Uri.https('jsonplaceholder.typicode.com', 'posts');
And if you want to add queryparametrs then use below code
final queryParameters =
{
'key' : 'value',
};
var uri= Uri.https('jsonplaceholder.typicode.com', 'posts',queryParameters);
And use this uri in place of Url.
final response = await http.get(uri);
I use HTTP for connection to API, and I have tried some flutter sdk like 2.5, 2.10.5, 3 but still have same issue often occur return connection closed before full header was received. and it's can occur in random api and all apps I build in flutter.
it's example of my code
Future<dynamic> getGoodSolution() async {
final url = Uri.parse('$url');
final headers = {HttpHeaders.contentTypeHeader: 'application/json', HttpHeaders.authorizationHeader: 'Bearer mytoken123'};
var map = <String, dynamic>{};
map["xxx"] = "123";
// print(headers);
try {
final response = await client.post(url, headers: headers, body: json.encode(map));
final data = xxxFromJson(response.body);
return data;
} catch (e) {
print(e);
return null;
}
}
I solved the problem by using the send() method of the HTTP (More info) package
Future<dynamic> getGoodSolution() async {
final url = Uri.parse('$url');
final headers = {HttpHeaders.contentTypeHeader: 'application/json',HttpHeaders.authorizationHeader: 'Bearer mytoken123'};
var map = <String, dynamic>{};
map["xxx"] = "123";
try {
var request = http.Request('POST', url);
request.headers.addAll(headers);
request.body = json.encode(map);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
final data = xxxFromJson(response.body);
return data;
} catch (e) {
print(e);
return null;
}
}
There is an issue ongoing on the Flutter repo which describes your problem.
One of the given workarounds is to use a HttpClient and to set the allowLegacyUnsafeRenegotiation property to true
void main() async {
final context = SecurityContext.defaultContext;
context.allowLegacyUnsafeRenegotiation = true;
final httpClient = HttpClient(context: context);
final client = IOClient(httpClient);
await client.get(Uri.parse('https://your_uri.net'));
}
This solution will only work on mobile though, the http package should not be used in Web mode.
This is my simple code
try{
final dynamic headers = await _getReqHeader();
http.Response res = await http.get(Uri.parse(url), headers: headers);
print("Dres2="+res.toString());
return _result(res);
}catch(e){
print("Dres3="+e.toString());
return _result({});
}
This code works well. But when use some url's I get type '_SimpleUri' is not a subtype of type 'String' error. In postman this url works perfectly. I could not find any information about _SimpleUri. How can I solve this problem?
The get method of the http package takes Uri.https(hostUrl , apiEndpoint) not Uri.parse.
The error appears because a simple URLs being passed to it. To fix this, you have to do this:
http.Response res = await http.get(Uri.https(host, url), headers: headers);
I had a similar issue and that's how I solved it.
static const baseUrl = "apihost.com";
Future<http.Response> _get(String url, {host = baseUrl}) async {
final header = <String, String>{};
return http.get(Uri.https(host, url), headers: header);
}
Future<String?> getData() async {
final response = await _get("/endpoint");
if (isSuccessful(response)) {
final json = jsonDecode(response.body);
} else {
print('GET failed [${response.statusCode}]:
${response.body}');
return null;
}
}
I am not sure what is going on with my function. I am trying to have a generic request function that I can use with any request method (GET, POST, etc...). Everything is working well, except for the POST response, it is missing data. I double checked what is expected to be returned and compared it with the response from Postman and my code. My code produces less data than expected and Postman.
Here is what I am doing
class HttpClientHandler {
String baseUrl = 'jsonplaceholder.typicode.com';
String path = '/posts';
static const Map<String, String> defaultHeaders = {'': ''};
static const Map<String, String> defaultBody = {'': ''};
Future<dynamic> request(HttpMethod method,
{Map<String, String> headers = defaultHeaders,
Map<String, dynamic> body}) async {
var uri = Uri.https(baseUrl, '$path');
var request = http.Request(method.type, uri);
request.headers.addAll(headers);
request.body = body.toString();
var response = await request.send();
if (response.statusCode >= 200 && response.statusCode <= 299) {
String rawData = await response.stream.transform(utf8.decoder).join();
return jsonDecode(rawData);
} else {
throw Exception();
}
}
}
The caller simply does the following:
var _client = HttpClientHandler();
var data = await _client.request(HttpMethod.POST, body: {'title': 'foo', 'body': 'bar', 'userId': 1});
print(data);
The response I get is:
{id: 101}
The expected response is:
{
"title": "foo",
"body": "bar",
"userId": "1",
"id": 101
}
I am using import 'package:http/http.dart' as http; package. Is this a stream, transform, or headers issue?
I found what was wrong in my implementation, I didn't jsonEncode my request body. The test API I am using here replies the same request body it receives. Since I wasn't encoding the body correctly, it only was recognizing the first data being sent.
So, the fix is to change this line:
request.body = body.toString();
to this line:
request.body = jsonEncode(body);
Also, I ended up parsing the stream byte to string differently, from:
String rawData = await response.stream.transform(utf8.decoder).join();
To:
String rawData = await response.stream.bytesToString();