aloisdeniel/http_extensions

Query Parameters Extension

Open

#2 opened on Jul 2, 2019

View on GitHub
 (3 comments) (0 reactions) (0 assignees)Dart (15 forks)github user discovery
enhancementgood first issue

Repository metrics

Stars
 (35 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

I was trying to figure out the best way to append query parameters with each request and ending up creating an extension. Here is what I put together.

Extension (request_extension.dart)

class RequestExtension extends Extension<RequestOptions> {
  final Logger logger;

  RequestExtension({RequestOptions defaultOptions = const RequestOptions(), this.logger})
      : super(defaultOptions: defaultOptions);

  Future<BaseRequest> _resolve(
      BaseRequest original, RequestOptions options) async {
    if (original is ExtensionRequest) {
      return ExtensionRequest(
          request: await _resolve(original.request, options),
          options: original.options);
    }

    if (original.url.hasScheme) {
      return original;
    }

    if (options.queryParameters == null) {
      return original;
    }

    if (options.queryParameters.isNotEmpty) {
      final url = original.url.replace(queryParameters: options.queryParameters);

      logger?.fine('Appended Query Parameters');

      if (original is Request) {
        var result = Request(original.method, url);
        if (original.headers != null) result.headers.addAll(original.headers);
        if (original.encoding != null) result.encoding = original.encoding;
        if (original.bodyBytes != null) result.bodyBytes = original.bodyBytes;

        return result;
      }

      if (original is StreamedRequest) {
        var result = Request(original.method, url);
        if (original.headers != null) result.headers.addAll(original.headers);
        result.bodyBytes = await original.finalize().toBytes();

        return result;
      }

      throw ArgumentError(
          "Failed to resolve request of type ${original.runtimeType}");
    } else {
      return original;
    }
  }

  @override
  Future<StreamedResponse> sendWithOptions(
      BaseRequest request, RequestOptions options) async {
    request = await _resolve(request, options);
    return await super.sendWithOptions(request, options);
  }
}

Options (request_options.dart)

class RequestOptions {
  final Map<String, String> queryParameters;

  const RequestOptions({this.queryParameters});
}

Example (main.dart)

Future main() async {
  final client = ExtendedClient(
    inner: Client(),
    extensions: [
      RequestExtension(),
    ],
  );

  var response = await client.getWithOptions('my-url-string', 
    options: [RequestOptions(queryParameters: {'option1': 'value1'}]);
}

Not sure if this is the best way to do this, you could I imagine add a parameter on each method call (get, put, delete, etc.) for the query params.

Contributor guide