π§© How to Pass a Request Body in a GET Request? Meet the New HTTP QUERY Method (RFC 10008)
β‘ A New HTTP Verb for Developers
The QUERY method (RFC 10008, June 2026) solves a longβstanding pain point: sending complex request bodies safely and cacheably without abusing GET or POST. Because QUERY is safe and idempotent, if a network drop happens, the client can automatically retry the request without risk of duplicating side effects - a major architectural win.
The Problem with GET and POST
GET Example (Fails with Complex Filters)
GET /api/products?category=electronics&tags=wireless,sale,new-arrival&price_min=100&price_max=1000&sort=rating_desc&page=2&limit=20&brand=Sony|Samsung&in_stock=true&discount_gte=10 HTTP/1.1
Host: shop.com
- Too long β URLs hit browser/server length limits.
- Leaky β Query strings show up in logs, browser history, and monitoring tools.
- Awkward encoding β Nested conditions (AND / OR) are hard to represent.
POST Example (Breaks Caching)
POST /api/products/search HTTP/1.1
Host: shop.com
Content-Type: application/json
{
"category": "electronics",
"tags": ["wireless", "sale", "new-arrival"],
"price_range": { "min": 100, "max": 1000 }
}
- Not cacheable β POST responses arenβt cached by browsers or CDNs.
- Wrong semantics β POST is meant for creating resources, not fetching.
π The Solution: QUERY
QUERY combines the best of both worlds: request body support like POST, but safe and cacheable like GET.
π¦ Example: Advanced Product Search
{
"category": "electronics",
"tags": ["wireless", "sale", "new-arrival"],
"price_range": { "min": 100, "max": 1000 },
"sort": { "field": "rating", "order": "desc" },
"pagination": { "page": 2, "limit": 20 },
"conditions": {
"or": [
{ "brand": "Sony" },
{ "brand": "Samsung" }
],
"and": [
{ "in_stock": true },
{ "discount": { "gte": 10 } }
]
}
}
QUERY Request
QUERY /api/products HTTP/1.1
Host: shop.com
Content-Type: application/json
Accept: application/json
{ ...payload above... }
π Core Comparison Matrix
| Metric | GET | POST | QUERY |
|---|---|---|---|
| Intended Use | Simple fetch | Create data | Complex fetch |
| Request Body | β No | β Yes | β Yes |
| Safe & Idempotent | β Yes | β No | β Yes |
| Cacheable | β Yes | β No | β Yes |
| Retry on Drop | β Risky | β Risky | β Safe |
| URI for Query | β Always | β No | β οΈ Optional via Location |
| URI for Result | β οΈ Optional | β οΈ Optional | β οΈ Optional via Content-Location |
| Discovery | β No | β No | β Accept-Query |
| Conditional Requests | β Yes | β No | β Yes |
| Redirection | β Yes | β Yes | β Yes (QUERYβQUERY or GET) |
π§ Real-World Code Examples
Frontend (QUERY with fetch)
async function searchProducts(filters) {
const response = await fetch('https://shop.com/api/products', {
method: 'QUERY',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(filters)
});
return response.json();
}
Backend (Express.js)
const express = require('express');
const app = express();
app.use(express.json());
app.all('/api/products', (req, res, next) => {
if (req.method !== 'QUERY') return next();
const filters = req.body;
const products = db.findProducts(filters);
res.setHeader('Cache-Control', 'public, max-age=3600');
res.json(products);
});
π CDN Support for QUERY with Body
RFC 10008 requires caches to incorporate both the request target and the body into cache keys:
Cache Key = Path + Body Hash
Path: /api/products
Body: {"category":"electronics","tags":["sale"]}
Body Hash: abcd1234
Final Key: /api/products:abcd1234
- Cloudflare β Cache rules + body hash
- Akamai β EdgeWorkers extend cache keys
- Fastly β VCL:
set req.hash += req.body; - AWS CloudFront β Lambda@Edge workaround (rewrite QUERY β GET + body hash)
- Google Cloud CDN β Proxy QUERY through Cloud Functions until native support arrives
π RFC 10008 Extra Features
- Discovery β Use OPTIONS or the
Accept-Queryheader to check if a resource supports QUERY - Location Header (URI for Query) β Server may assign a URI representing the query definition
- Content-Location Header (URI for Result) β Server may assign a URI representing the result set
- Conditional Requests β QUERY supports ETag and
If-Modified-Sincefor cache validation - Redirection β QUERY can be redirected but must remain QUERY or map to GET
- Security β QUERY avoids leaking sensitive data in URIs, but servers must handle generated URIs carefully
β FAQ Highlights
- π οΈ Frameworks β Express, Django, Spring, and FastAPI donβt yet have
app.query(), but you can intercept QUERY as a raw method string - π Browsers β All major browsers allow sending QUERY via
fetch; tooling may still show it as a custom verb - π Monitoring β Grafana/Prometheus donβt yet classify QUERY; treat it as a custom verb in logs until native support arrives
β¨ Closing Thoughts
The QUERY method (RFC 10008, June 2026) is a true architectural upgrade:
- Safe, idempotent, cacheable
- Supports complex request bodies with arrays, sorting, pagination, and nested conditions
- Enables automatic retries after network drops
- Works with CDNs when cache keys include body hashes
- Adds discovery, conditional requests, redirection, and URI assignment for queries/results
π For full details, see the official spec: RFC 10008 β The HTTP QUERY Method
Comments
No comments yet. Start the discussion.