Environment information
Version: 5.2.1 (also present on the 4.x line — same req.fresh implementation)
Platform: Microsoft Windows NT 10.0.26200.0 x64
Node.js version: v24.18.0 (QUERY requires Node >= 22, where http.METHODS includes QUERY)
Any other relevant information:
req.fresh (lib/request.js) short-circuits to false for any method other than GET/HEAD, so res.send/res.json never emit a 304 Not Modified for a QUERY request even when the client sends a matching If-None-Match.
As far as I can tell, QUERY is a safe, idempotent, cacheable method whose responses explicitly support conditional revalidation, as per https://datatracker.ietf.org/doc/rfc10008/, so it should behave like GET/HEAD here.
What steps will reproduce the bug?
Minimal app:
const express = require('express')
const app = express()
app.query('/search', (req, res) => {
res.set('ETag', '"abc"')
res.json({ results: [] })
})
app.listen(3000)
Send a conditional QUERY with a matching If-None-Match:
# Sends a body (the point of QUERY) and the ETag the server previously returned
curl -i -X QUERY http://localhost:3000/search \
-H 'Content-Type: application/json' \
-H 'If-None-Match: "abc"' \
--data '{"q":"x"}'
Observed: 200 OK with the full response body every time.
Expected: 304 Not Modified with an empty body — the same behavior an identical GET produces, since the response ETag matches the request's If-None-Match.
Equivalent reproduction against req.fresh directly (mirrors the test suite style):
const app = express()
app.use((req, res) => {
res.set('ETag', '"12345"')
res.send(req.fresh) // GET -> true (304); QUERY -> false (200) before the fix
})
// request(app).query('/').set('If-None-Match', '"12345"') => 200 'false', expected 304
Environment information
Version:
5.2.1(also present on the4.xline — samereq.freshimplementation)Platform: Microsoft Windows NT 10.0.26200.0 x64
Node.js version:
v24.18.0(QUERY requires Node >= 22, wherehttp.METHODSincludesQUERY)Any other relevant information:
req.fresh(lib/request.js) short-circuits tofalsefor any method other thanGET/HEAD, sores.send/res.jsonnever emit a304 Not Modifiedfor aQUERYrequest even when the client sends a matchingIf-None-Match.As far as I can tell, QUERY is a safe, idempotent, cacheable method whose responses explicitly support conditional revalidation, as per https://datatracker.ietf.org/doc/rfc10008/, so it should behave like
GET/HEADhere.What steps will reproduce the bug?
Minimal app:
Send a conditional QUERY with a matching
If-None-Match:Observed:
200 OKwith the full response body every time.Expected:
304 Not Modifiedwith an empty body — the same behavior an identicalGETproduces, since the responseETagmatches the request'sIf-None-Match.Equivalent reproduction against
req.freshdirectly (mirrors the test suite style):