dio
dio copied to clipboard
Prevent encoding query parameters
New Issue Checklist
- [x] I have searched for a similar issue in the project and found none
dependencies:
flutter:
sdk: flutter
http: ^0.13.4
json_annotation: ^4.4.0
dio: ^4.0.4
Issue Description and Steps
https://github.com/flutterchina/dio/blob/develop/dio/lib/src/options.dart#L545
The above code always does the encoding of query parameters by using +
instead of spaces. The issue is, some servers do not understand the +
, instead they use %20
.
Tried to manually encode the query paramater value but then it ends up to duplicated encoding.
- How to prevent encoding or provive a Query Parameter encoder to support this case ?
// Current (Term=Hello World)
baseUrl/search?term=HELLO+WORLD
Expected (Term=Hello World)
// baseUrl/search?term=HELLO%20WORLD
Currently using the below workaround.
class EncodingInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (options.queryParameters.isEmpty) {
super.onRequest(options, handler);
return;
}
final queryParams = _getQueryParams(options.queryParameters);
handler.next(
options.copyWith(
path: _getNormalizedUrl(options.path, queryParams),
queryParameters: Map.from({}),
),
);
}
String _getNormalizedUrl(String baseUrl, String queryParams) {
if (baseUrl.contains("?")) {
return baseUrl + "&$queryParams";
} else {
return baseUrl + "?$queryParams";
}
}
String _getQueryParams(Map<String, dynamic> map) {
String result = "";
map.forEach((key, value) {
result += "$key=${Uri.encodeComponent(value)}&";
});
return result;
}
}
https://github.com/flutterchina/dio/blob/develop/dio/lib/src/transformer.dart#L45
Can be fixed by using Uri.encodeComponent(value)
instead.
Currently using the below workaround.
class EncodingInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { if (options.queryParameters.isEmpty) { super.onRequest(options, handler); return; } final queryParams = _getQueryParams(options.queryParameters); handler.next( options.copyWith( path: _getNormalizedUrl(options.path, queryParams), queryParameters: Map.from({}), ), ); } String _getNormalizedUrl(String baseUrl, String queryParams) { if (baseUrl.contains("?")) { return baseUrl + "&$queryParams"; } else { return baseUrl + "?$queryParams"; } } String _getQueryParams(Map<String, dynamic> map) { String result = ""; map.forEach((key, value) { result += "$key=${Uri.encodeComponent(value)}&"; }); return result; } }
https://github.com/flutterchina/dio/blob/develop/dio/lib/src/transformer.dart#L45 Can be fixed by using
Uri.encodeComponent(value)
instead.
Thanks, it works with me
Currently using the below workaround.
class EncodingInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { if (options.queryParameters.isEmpty) { super.onRequest(options, handler); return; } final queryParams = _getQueryParams(options.queryParameters); handler.next( options.copyWith( path: _getNormalizedUrl(options.path, queryParams), queryParameters: Map.from({}), ), ); } String _getNormalizedUrl(String baseUrl, String queryParams) { if (baseUrl.contains("?")) { return baseUrl + "&$queryParams"; } else { return baseUrl + "?$queryParams"; } } String _getQueryParams(Map<String, dynamic> map) { String result = ""; map.forEach((key, value) { result += "$key=${Uri.encodeComponent(value)}&"; }); return result; } }
https://github.com/flutterchina/dio/blob/develop/dio/lib/src/transformer.dart#L45 Can be fixed by using
Uri.encodeComponent(value)
instead.
I suggest you this change to avoid errors on the qp's types sent:
String _getQueryParams(Map<String, dynamic> map) { String result = ""; map.forEach((key, value) { result += value.runtimeType == String ? "$key=${Uri.encodeComponent(value)}&" : "$key=$value&"; }); return result; }
Hi everyone. According to Uri.encodeQueryComponent
that is used in Transformer.urlEncodeMap
, it's the right choice of the API. But I also want to test if I can provide another solution to change the code base:
Try to replace: https://github.com/flutterchina/dio/blob/9040bde4a07ffe4e201e4ec014242a16eb69d926/dio/lib/src/options.dart#L545-L550
To this:
// Normalize the url.
return Uri.parse(url)
.replace(queryParameters: queryParameters)
.normalizePath();
This will drop the usage of the ListFormat
, but please let me know if it works.
This is completed because... there's a way to avoid encoding query parameters without the above workaround?
The above workaround doesn't work for me. The parameters still gets encoded. Aka I want to send a query param like so:
?param=auth0|someId
But even if I explicitly overwrite the above without encoding I still get
?param=auth0%7CsomeId
Which is pretty annoying. I have no other interceptors implemented / connected.