# Has Your Stack Noticed the QUERY Method Is Standard Now

Published 2026-07-07. Updated 2026-09-17.
Canonical URL https://log.delaa.dev/blog/2026-07-07-has-your-stack-noticed-query-method-standard

> RFC 10008 gives HTTP a safe, cacheable request with a body. I sent QUERY through Node, fetch, Next.js and PHP to see what actually accepts it. Verbatim results included.

---

<Image
  src="/images/http-query-method-stack-support/hero.png"
  alt="An envelope icon branching into four stack logos, each marked with a solid or faded checkmark showing support status"
  width={2000}
  height={1125}
  className="rounded-lg"
/>

On June 15, 2026, the IETF published [RFC 10008](https://www.rfc-editor.org/info/rfc10008/),
the HTTP `QUERY` method. It is the first new standard HTTP verb since
`PATCH` in 2010, and it closes a gap that API designers have worked
around for decades: a request that is **safe and idempotent like GET,
but carries a body like POST**.

Plenty of articles already explain the RFC. This one does something
different: it sends `QUERY` through a real 2026 stack, Node.js, `fetch`,
Next.js, PHP, and records exactly what each layer does with it. In
short, the client side is ready, the server side mostly is not,
and the failure modes range from a silent whitelist to a hard `501`.

## Why QUERY exists

Every API with non-trivial search has faced this choice:

- `GET /search?filter=...`: correct semantics (safe, cacheable,
  retryable), but query input lives in the URL. Length limits, encoding
  pain, and sensitive criteria leaking into server logs, browser history,
  and `Referer` headers.
- `POST /search`. The body solves all of that, but the semantics are
  wrong: not safe, not idempotent, effectively uncacheable, and
  intermediaries won't auto-retry a failed request because POST promises
  nothing about side effects.

`QUERY` takes the body from POST and the semantics from GET.

| | GET | QUERY | POST |
|---|---|---|---|
| Safe | yes | yes | no |
| Idempotent | yes | yes | no |
| Request body | undefined | yes | yes |
| Cacheable | yes | yes (cache key includes the body) | practically no |

Two spec details worth knowing before deploying anything:

- The cache key for a QUERY response **must incorporate the request
  content**. CDNs and reverse proxies need new logic before QUERY
  responses become cacheable in practice.
- QUERY is **not CORS-safelisted**. Browser requests will trigger a
  preflight `OPTIONS`. Plan for it.

## The experiment

Versions tested: Node.js v22.11.0, Next.js 16.2.9, PHP 8.5.4 (built-in
dev server), on Linux. Each test is reproducible with the commands shown.

### The Node.js parser already knows QUERY

```bash
node -e "console.log(require('http').METHODS.includes('QUERY'))"
# true
```

Node's HTTP parser (llhttp) accepts `QUERY` as a valid method token. A
raw `http.createServer` receives the request and reports
`req.method === 'QUERY'`. No flags, no configuration.

### fetch works end-to-end

```js
const res = await fetch('http://127.0.0.1:3000/', {
  method: 'QUERY',
  body: '{"filter": {"status": "active"}}',
})
```

`fetch` (undici in Node, and the browser implementations) sends the
method and the body without complaint. The server sees `QUERY`. The
client side, the work is, for practical purposes, already done.

### Next.js 16 ships a silent whitelist

Next.js App Router route handlers export functions named after HTTP
methods. So the natural move is:

```ts
// app/api/search/route.ts
export async function QUERY(request: Request) { /* ... */ }
```

This does not work, and nothing tells you why. The list of methods
Next.js will route is hardcoded in
`next/dist/server/web/http.js`:

```js
const HTTP_METHODS = [
    'GET',
    'HEAD',
    'OPTIONS',
    'POST',
    'PUT',
    'DELETE',
    'PATCH'
];
```

An exported `QUERY` function is simply never wired up. No error, no
warning, no 405. Meanwhile, page routes respond `200` to a QUERY request
as if it were a GET, which is its own semantic oddity.

### PHP built-in server returns a hard 501

```bash
php -S 127.0.0.1:8080 &
curl -X QUERY -d '{"q": 1}' http://127.0.0.1:8080/index.php
```

```
501 Not Implemented
Request method not supported.
```

The `php -S` development server rejects the method before your code
runs. `$_SERVER['REQUEST_METHOD']` never sees it. Production SAPIs
(PHP-FPM behind nginx) pass unknown method tokens through to the
application, so this is specifically a development-environment wall,
the kind of asymmetry that makes a feature work in production and fail
on every developer's machine.

### .NET 10 is the exception

For contrast, .NET 10 (LTS, November 2025) shipped with built-in QUERY
support on both `HttpClient` and ASP.NET Core, the first major
framework to do so. Two of the RFC's three authors, James Snell
(Cloudflare) and Mike Bishop (Akamai), work at infrastructure companies
with a direct stake in QUERY's cacheability story, which tracks with
.NET's infrastructure-heavy customer base moving first.

## What this means if you want QUERY today

You can accept it at the edge of your own Node servers right now. The
parser and `fetch` are ready, frameworks are the missing layer. Advertise
support with the RFC's `Accept-Query` response header so clients can
feature-detect instead of guessing which query media types a resource
accepts.

Keep the POST fallback around for years regardless. PATCH was
standardized in 2010 and some frameworks still route it inconsistently;
method adoption moves at the pace of the slowest middlebox. And budget
for the CORS preflight. QUERY isn't safelisted, so a browser-based
rollout doubles your request count until CDNs and browsers optimize
for it.

I ran this whole experiment because a client asked why their
Next.js API route silently ignored a QUERY request from a partner
integration. The answer took twenty minutes to find once I knew where
to look, and about two hours before that.

The RFC is the easy part. The interesting phase is the one we are in
now. A correct, useful standard slowly negotiating with twenty years of
deployed software that has never heard of it.

## Try it yourself

Every test in this article is reproducible from a companion lab,
versions pinned to the ones above, so it keeps demonstrating this exact
snapshot even after newer releases change the picture:

```bash
npx degit imdela/log-labs/http-query my-lab
cd my-lab
./run-demo.sh
```

The script starts a raw Node server (which accepts QUERY and answers
with filtered results), the Next.js app (405), and the PHP dev server in
a container (501), sends the same request to all three, and prints what
came back. The lab's [README](https://github.com/imdela/log-labs/tree/main/http-query)
covers running each server by hand.

---

Delaa
