Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent encoding query parameters #1445

Closed
1 task done
xeinebiu opened this issue Mar 16, 2022 · 5 comments
Closed
1 task done

Prevent encoding query parameters #1445

xeinebiu opened this issue Mar 16, 2022 · 5 comments

Comments

@xeinebiu
Copy link

xeinebiu commented Mar 16, 2022

New Issue Checklist

  • 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
@xeinebiu
Copy link
Author

xeinebiu commented Mar 16, 2022

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.

@minhdangoz
Copy link

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

@mb180594b
Copy link

mb180594b commented Nov 24, 2022

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;
  }

@AlexV525
Copy link
Member

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.

@lucavenir
Copy link

lucavenir commented Jan 18, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants