How do you add query parameters to a Dart http request?
Asked Answered
S

13

125

How do you correctly add query parameters to a Dart http get request? I been unable to get my request to respond correctly when trying to append the '?param1=one&param2=two' to my url, yet it works correctly in Postman. Here's the gist of my code:

    final String url = "https://www.myurl.com/api/v1/test/";
    String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two";

    Map<String, String> qParams = {
     'param1': 'one',
     'param2': 'two',
    };


   var res = await http
      .get(Uri.encodeFull("$url${widget.pk}/"),
      headers: {HttpHeaders.authorizationHeader: "Token $token", 
        HttpHeaders.contentTypeHeader: "application/json"},
);

The ${widget.pk} is simply a integer value being pass (See the value 123 in the workingStringInPostman variable.

The qParams is there for connivence, in case a Uri parameter is needed.

A code example would be welcomed.

Syrup answered 15/10, 2018 at 20:33 Comment(0)
L
211

You'll want to construct a Uri and use that for the request. Something like

final queryParameters = {
  'param1': 'one',
  'param2': 'two',
};
final uri =
    Uri.https('www.myurl.com', '/api/v1/test', queryParameters);
final response = await http.get(uri, headers: {
  HttpHeaders.authorizationHeader: 'Token $token',
  HttpHeaders.contentTypeHeader: 'application/json',
});

See https://api.dartlang.org/stable/2.0.0/dart-core/Uri/Uri.https.html

Longfellow answered 15/10, 2018 at 20:48 Comment(5)
The splitting up of the host and path was the answer.Syrup
for some reason, the application stops after Uri.https like an exception, but without error, it just stops.Hexamerous
Got error if the url is local host with port like localhost:5001.Filature
not working for local address define path of apiHarmaning
To create a URI for a localhost address. Uri.http('localhost:5001', '/api/v1/whatever', {'param1': 'one'}). If you are hitting issues with https and localhost it could be a certificate issue.Longfellow
A
52

this is more simple

final uri = Uri.parse('$baseUrl/v1/endpoint').replace(queryParameters: {
      'page': page,
      'itemsPerPage': itemsPerPage,
    });
final response = await client.get(uri);
Agentive answered 30/8, 2021 at 17:31 Comment(2)
this is very easy for the HTTP package not for the Dio package.Lyceum
Doesn't work properly it adds only the first two query paramsDrinkwater
R
38

If you dont want to override the scheme of base endpoint url, use the below technique to convert the map to query string and append it to the base endpoint url

var endpointUrl = 'https://www.myurl.com/api/v1/user';
Map<String, String> queryParams = {
  'param1': '1',
  'param2': '2'
};

var headers = {
  HttpHeaders.authorizationHeader: 'Token $token',
  HttpHeaders.contentTypeHeader: 'application/json',
}

String queryString = Uri.parse(queryParameters: queryParams).query;

var requestUrl = endpointUrl + '?' + queryString; // result - https://www.myurl.com/api/v1/user?param1=1&param2=2
var response = await http.get(requestUrl, headers: headers);
Redundancy answered 23/10, 2020 at 12:45 Comment(5)
Unfortunately, this doesn't work anymore. An error is thrown at http.get(requestUrl....) The argument type 'String' can't be assigned to the parameter type 'Uri'.Guildsman
@OjonugwaJudeOchalifu just wrap the String in Uri.parse().Berke
I don't see any parameter queryParameters of Uri.parseSusan
Parameter queryParameters does not exists in Uri.parse()Rillings
instead of Uri.parse() use Uri(queryParameters: queryParams)Marvamarve
F
8

Got the same question. The accepted answer won't work if my url is localhost with port like https://localhost:5001. After spending 1 day to search for solution, I come up with Dio library. Following is my solution using Dio:

var _dio = new Dio();
var options = new Options;
options.headers['Authorization'] = 'bearer $token';
options.contentType = 'application/json';
String url = "https://www.myurl.com";
Map<String, String> qParams = {
  'param1': 'one',
  'param2': 'two',
};

var res = await _dio.get(url, options: options, queryParameters: qParams);

Hope this helps.

Filature answered 2/11, 2019 at 5:47 Comment(4)
getting this error still - Unhandled Exception: NoSuchMethodError: The method '[]' was called on null. E/flutter (12741): Receiver: null E/flutter (12741): Tried calling: []("BankName")Harmaning
can you suggest any solution?Harmaning
In order to get a response as a List<String>, I had to do _dio.get<List<dynamic>>(...).data.cast<String>();. If somebody knows a better way, feel free to let me know.Subalpine
It should be options.headers = {'Authorization': 'bearer $token'};Subalpine
J
6

Use Uri constructor to build your query, it has a queryParameter property.

var uri = Uri(
  scheme: 'https',
  host: 'example.com',
  path: '/foo/bar',
  fragment: 'baz',
  queryParameters: _yourQueryParameters,
);

var response = await http.get(uri);
if (response.statusCode == 200) {
  var json = jsonDecode(response.body);
  // Do whatever you want to do with json. 
}
Judge answered 29/9, 2020 at 10:59 Comment(0)
C
6

Use Uri to pass query parameters like.

final String url = "https://www.myurl.com/api/v1/test/${widget.pk}/";

Map<String, String> qParams = {
 'param1': 'one',
 'param2': 'two',
};
Map<String, String> header = {
HttpHeaders.authorizationHeader: "Token $token", 
    HttpHeaders.contentTypeHeader: "application/json"
};

Uri uri = Uri.parse(url);
final finalUri = uri.replace(queryParameters: qParams); //USE THIS

final response = await http.get(
  finalUri,
  headers: header,
);
Crackle answered 22/3, 2021 at 15:23 Comment(0)
D
4

The accepted answer didn't work for me but adding a '&' without quotes to end of the URL solves my problem. In this case, change the following line:

String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two";

to this: (Notice the '&' at the end).

String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two&";
Dirk answered 19/10, 2019 at 17:0 Comment(1)
Most simple and best solution)Soissons
D
2

There is a dart package that provides some helper classes for http requests.

BasicUtils : https://github.com/Ephenodrom/Dart-Basic-Utils

Install it with:

dependencies:
  basic_utils: ^1.4.0

Usage

You can add a map of headers and query parameters to each request. See the example :

// Define some headers and query parameters
Map<String, String> headers = {
  "Accept": "application/json"
};
Map<String, String> queryParameters = {
  "foo": "bar"
};

// Body
String body = "{ 'some':'json'}";

// Send request
Map<String, dynamic> responseData = await HttpUtils.postForJson("api.com/dosomething", body,
      headers: headers, queryParameters: queryParameters);

Additional information :

These are all methods from the HttpUtils class.

Future<Map<Response> getForFullResponse(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> getForJson(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<String> getForString(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<Map<Response> postForFullResponse(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> postForJson(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> postForString(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Response> putForFullResponse(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> putForJson(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> putForString(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Response deleteForFullResponse(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> deleteForJson(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> deleteForString(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Map<String, dynamic> getQueryParameterFromUrl(String url);
String addQueryParameterToUrl(String url, Map<String, dynamic> queryParameters);
Darceydarci answered 16/7, 2019 at 8:6 Comment(0)
B
1

The following function copied from flutter code can be used to create the query string part only:

String queryString(Map<String, dynamic> queryParameters) {
  var result = StringBuffer();
  var separator = "";

  void writeParameter(String key, String? value) {
    result.write(separator);
    separator = "&";
    result.write(Uri.encodeQueryComponent(key));
    if (value != null && value.isNotEmpty) {
      result.write("=");
      result.write(Uri.encodeQueryComponent(value));
    }
  }

  queryParameters.forEach((key, value) {
    if (value == null || value is String) {
      writeParameter(key, value);
    } else {
      Iterable values = value;
      for (String value in values) {
        writeParameter(key, value);
      }
    }
  });
  return result.toString();
}

Usage:

var q = queryString({"a":"b&", "c":["1","xyz"]});
// a=b%26&c=1&c=xyz
Blindfold answered 12/1, 2022 at 17:50 Comment(0)
I
0

I made a little util function which resolves the authority / unencodedPath parameters for Uri creation.

Uri createUri(String url, [Map<String, String> queryParameters]) {
  var isHttp = false;
  if (url.startsWith('https://') || (isHttp = url.startsWith('http://'))) {
    var authority = url.substring((isHttp ? 'http://' : 'https://').length);
    String path;
    final index = authority.indexOf('/');

    if (-1 == index) {
      path = '';
    } else {
      path = authority.substring(index);
      authority = authority.substring(0, authority.length - path.length);
    }

    if (isHttp) {
      return Uri.http(authority, path, queryParameters);
    } else {
      return Uri.https(authority, path, queryParameters);
    }
  } else if (url.startsWith('localhost')) {
    return createUri('http://' + url, queryParameters);
  }

  throw Exception('Unsupported scheme');
}

Here is the example code which uses it:

final String url = 'https://www.myurl.com/api/v1/test/${widget.pk}';
Map<String, String> qParams = {
  'param1': 'one',
  'param2': 'two',
};

var res = await http.get(
  createUri(url, qParams),
  headers: {
    HttpHeaders.authorizationHeader: "Token $token",
    HttpHeaders.contentTypeHeader: "application/json"
  },
);
Ibo answered 18/2, 2021 at 22:10 Comment(0)
G
0

U can use this:

String _getParamsFromBody( Map<String, dynamic>? body) {
String params = '?';
for (var i = 0; i < body!.keys.length; i++) {
  params += '${List.from(body!.keys)[i]}=${List.from(body!.values)[i]}';
  if (i != body!.keys.length - 1) {
    params += '&';
  }
}
log(params);
return params;

}

Uri.parse("https://www.myurl.com/api/v1/test"+ _getParamsFromBody({'param1':'value1','param2':'value2}))
General answered 26/2, 2022 at 9:56 Comment(1)
Beware! This approach does NOT escape the query parametersHallett
N
0
  final uri = Uri.parse("${ApiConstants.baseUrl}/blog/post/blog-post-list");
  uri.replace(queryParameters: {"location": location});
  final Response response = await _apiRepository.getApi(uri);
  if (response.statusCode == 200 || response.statusCode == 201) {
    final content = await jsonDecode(response.body);
    final data = await content["data"] as List;
    List<PostModel> list = [];
    for (var i in data) {
      final postModel = PostModel.fromJson(i);
      list.add(postModel);
    }

this works as of today

Nietzsche answered 24/12, 2022 at 14:11 Comment(0)
R
-1

This is worked for me.

  _init() async {
    DateTime endDate = DateTime.now();
    DateTime startDate = endDate.subtract(Duration(days: 30 * 11));
    var response = await Api.get(
        "mover/dashboard/column-chart?start=$startDate&end=$endDate");
    if (response.statusCode == 200) {
      var json = jsonDecode(response.body);
      if (mounted) {
        setState(() {});
      }
    }
  }

Api.dart

  static Future<http.Response> get(path) async {
    String? token = await Store.read('token');
    try {
      var response = await http.get(
        Uri.parse('$basePath/api/moving/$path'),
        headers: {
          'Authorization': 'Bearer $token',
          'Content-Type': 'application/json'
        },
      );
      return response;
    } catch (err) {
      return http.Response('${err.toString()}', 400);
    }
  }
Rafiq answered 12/4, 2023 at 5:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.