From e28131f8276f3e0a6adc0bdf52dcb8483fdc73fa Mon Sep 17 00:00:00 2001 From: ankit1324 Date: Sun, 12 Jul 2026 17:03:39 +0530 Subject: [PATCH] fix: enable conditional revalidation (304) for QUERY requests req.fresh short-circuited to false for any method other than GET/HEAD, so res.send/res.json never emitted 304 Not Modified for a QUERY request even when the client sent a matching If-None-Match. QUERY is a safe, idempotent, cacheable method whose responses support conditional revalidation, so it should participate in freshness checks like GET/HEAD. fixes #7365 --- lib/request.js | 4 ++-- test/req.fresh.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/request.js b/lib/request.js index 68243f52b6d..1eb7f9ca16a 100644 --- a/lib/request.js +++ b/lib/request.js @@ -471,8 +471,8 @@ defineGetter(req, 'fresh', function(){ var res = this.res var status = res.statusCode - // GET or HEAD for weak freshness validation only - if ('GET' !== method && 'HEAD' !== method) return false; + // GET, HEAD, or QUERY for weak freshness validation only + if ('GET' !== method && 'HEAD' !== method && 'QUERY' !== method) return false; // 2xx or 304 as per rfc2616 14.26 if ((status >= 200 && status < 300) || 304 === status) { diff --git a/test/req.fresh.js b/test/req.fresh.js index 3bf6a1f65a7..5cb11f09a1d 100644 --- a/test/req.fresh.js +++ b/test/req.fresh.js @@ -2,6 +2,7 @@ var express = require('../') , request = require('supertest'); +var shouldSkipQuery = require('./support/utils').shouldSkipQuery describe('req', function(){ describe('.fresh', function(){ @@ -20,6 +21,41 @@ describe('req', function(){ .expect(304, done); }) + it('should return true for QUERY when the resource is not modified', function(done){ + if (shouldSkipQuery(process.versions.node)) { + this.skip() + } + var app = express(); + var etag = '"12345"'; + + app.use(function(req, res){ + res.set('ETag', etag); + res.send(req.fresh); + }); + + request(app) + .query('/') + .set('If-None-Match', etag) + .expect(304, done); + }) + + it('should return false for QUERY when the resource is modified', function(done){ + if (shouldSkipQuery(process.versions.node)) { + this.skip() + } + var app = express(); + + app.use(function(req, res){ + res.set('ETag', '"123"'); + res.send(req.fresh); + }); + + request(app) + .query('/') + .set('If-None-Match', '"12345"') + .expect(200, 'false', done); + }) + it('should return false when the resource is modified', function(done){ var app = express();