http_query

pub package CI License: BSD-3-Clause

A client and server SDK for the HTTP QUERY method (RFC 10008) in Dart.

QUERY is a safe and idempotent request method that carries a request body describing a query to run against the target resource. It combines the best of GET (safe, cacheable, retryable) and POST (arbitrary request body): the query travels in the body instead of the URI.

Sending a query

The async client is built on package:http.

import 'package:http_query/http_query.dart';

Future<void> main() async {
  final client = QueryClient();

  // Raw body + content type
  final resp = await client.queryString(
    'https://example.org/search',
    'application/sql',
    'SELECT 1',
  );

  // JSON in, JSON out (validates the status)
  final results = await client.queryJsonInto(
    'https://example.org/search',
    {'q': 'dart'},
  );

  client.close();
}

Result vs. equivalent resource

A QUERY response can advertise two distinct GET-retrievable URIs (RFC 10008 ยง2.3โ€“2.4):

  • Content-Location โ€” the stored result of the query just run. QueryClient.fetchResult follows it.
  • Location โ€” the equivalent resource, whose GET re-runs the query. QueryClient.fetchEquivalent follows it.

Discovering support

Accept-Query is an RFC 9651 Structured Fields List; it is parsed and serialized correctly (quoted strings, parameters, */* and type/* wildcards).

final discovery = await client.options('https://example.org/search');
if (discovery.supportsQuery) {
  print(discovery.acceptQuery);
}

Serving QUERY

The server helpers are framework-agnostic (they work on a method string and a header map), so they plug into dart:io HttpServer, shelf, etc. They enforce the RFC's rules: 400 for a missing Content-Type, 415 for an unsupported query media type, 405 for non-QUERY methods.

final rejection = checkQueryRequest(method, headers, ['application/json']);
if (rejection != null) {
  // respond with rejection.status  (400 / 405 / 415)
} else {
  // evaluate the query in the request body
}

Caching

Unlike GET, a QUERY cache entry must be keyed on the request body:

final key = cacheKey(
  'https://example.org/search',
  mediaTypeJson,
  utf8.encode('{"q":"dart"}'),
);

License

BSD-3-Clause.

Libraries

http_query
A client and server SDK for the HTTP QUERY method (RFC 10008).