From 9382f71545d9d67fd325eb6841c196b5325a30c0 Mon Sep 17 00:00:00 2001 From: "alexander.akait" Date: Mon, 19 Aug 2024 17:42:26 +0300 Subject: [PATCH 1/6] fix: ignore status message for HTTP/2 --- index.js | 5 +- test/support/utils.js | 18 +- test/test.js | 985 +++++++++++++++++++++++------------------- 3 files changed, 561 insertions(+), 447 deletions(-) diff --git a/index.js b/index.js index f628e42..9ed59f7 100644 --- a/index.js +++ b/index.js @@ -276,7 +276,10 @@ function send (req, res, status, headers, message) { // response status res.statusCode = status - res.statusMessage = statuses.message[status] + + if (req.httpVersionMajor < 2) { + res.statusMessage = statuses.message[status] + } // remove any content headers res.removeHeader('Content-Encoding') diff --git a/test/support/utils.js b/test/support/utils.js index 72c1fbe..8734159 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -6,7 +6,8 @@ var SlowWriteStream = require('./sws') exports.assert = assert exports.createError = createError -exports.createServer = createServer +exports.createHTTPServer = createHTTPServer +exports.createHTTP2Server = createHTTP2Server exports.createSlowWriteStream = createSlowWriteStream exports.rawrequest = rawrequest exports.request = request @@ -26,7 +27,20 @@ function createError (message, props) { return err } -function createServer (err, opts) { +function createHTTPServer (err, opts) { + return http.createServer(function (req, res) { + var done = finalhandler(req, res, opts) + + if (typeof err === 'function') { + err(req, res, done) + return + } + + done(err) + }) +} + +function createHTTP2Server (err, opts) { return http.createServer(function (req, res) { var done = finalhandler(req, res, opts) diff --git a/test/test.js b/test/test.js index 0b5d15c..61e4658 100644 --- a/test/test.js +++ b/test/test.js @@ -6,7 +6,8 @@ var utils = require('./support/utils') var assert = utils.assert var createError = utils.createError -var createServer = utils.createServer +var createHTTPServer = utils.createHTTPServer +var createHTTP2Server = utils.createHTTP2Server var createSlowWriteStream = utils.createSlowWriteStream var rawrequest = utils.rawrequest var request = utils.request @@ -18,557 +19,653 @@ var describeStatusMessage = !/statusMessage/.test(http.IncomingMessage.toString( ? describe.skip : describe -describe('finalhandler(req, res)', function () { - describe('headers', function () { - it('should ignore err.headers without status code', function (done) { - request(createServer(createError('oops!', { - headers: { 'X-Custom-Header': 'foo' } - }))) - .get('/') - .expect(shouldNotHaveHeader('X-Custom-Header')) - .expect(500, done) - }) - - it('should ignore err.headers with invalid res.status', function (done) { - request(createServer(createError('oops!', { - headers: { 'X-Custom-Header': 'foo' }, - status: 601 - }))) - .get('/') - .expect(shouldNotHaveHeader('X-Custom-Header')) - .expect(500, done) - }) +const servers = [ + ['http', createHTTPServer], + ['http2', createHTTP2Server] +] + +for (var i = 0; i < servers.length; i++) { + const name = servers[i][0] + const createServer = servers[i][1] + + describe(name, () => { + describe('headers', function () { + it('should ignore err.headers without status code', function (done) { + request(createServer(createError('oops!', { + headers: { 'X-Custom-Header': 'foo' } + }))) + .get('/') + .expect(shouldNotHaveHeader('X-Custom-Header')) + .expect(500, done) + }) - it('should ignore err.headers with invalid res.statusCode', function (done) { - request(createServer(createError('oops!', { - headers: { 'X-Custom-Header': 'foo' }, - statusCode: 601 - }))) - .get('/') - .expect(shouldNotHaveHeader('X-Custom-Header')) - .expect(500, done) - }) + it('should ignore err.headers with invalid res.status', function (done) { + request(createServer(createError('oops!', { + headers: { 'X-Custom-Header': 'foo' }, + status: 601 + }))) + .get('/') + .expect(shouldNotHaveHeader('X-Custom-Header')) + .expect(500, done) + }) - it('should include err.headers with err.status', function (done) { - request(createServer(createError('oops!', { - headers: { 'X-Custom-Header': 'foo=500', 'X-Custom-Header2': 'bar' }, - status: 500 - }))) - .get('/') - .expect('X-Custom-Header', 'foo=500') - .expect('X-Custom-Header2', 'bar') - .expect(500, done) - }) + it('should ignore err.headers with invalid res.statusCode', function (done) { + request(createServer(createError('oops!', { + headers: { 'X-Custom-Header': 'foo' }, + statusCode: 601 + }))) + .get('/') + .expect(shouldNotHaveHeader('X-Custom-Header')) + .expect(500, done) + }) - it('should include err.headers with err.statusCode', function (done) { - request(createServer(createError('too many requests', { - headers: { 'Retry-After': '5' }, - statusCode: 429 - }))) - .get('/') - .expect('Retry-After', '5') - .expect(429, done) - }) + it('should include err.headers with err.status', function (done) { + request(createServer(createError('oops!', { + headers: { 'X-Custom-Header': 'foo=500', 'X-Custom-Header2': 'bar' }, + status: 500 + }))) + .get('/') + .expect('X-Custom-Header', 'foo=500') + .expect('X-Custom-Header2', 'bar') + .expect(500, done) + }) - it('should ignore err.headers when not an object', function (done) { - request(createServer(createError('oops!', { - headers: 'foobar', - statusCode: 500 - }))) - .get('/') - .expect(500, done) - }) - }) + it('should include err.headers with err.statusCode', function (done) { + request(createServer(createError('too many requests', { + headers: { 'Retry-After': '5' }, + statusCode: 429 + }))) + .get('/') + .expect('Retry-After', '5') + .expect(429, done) + }) - describe('status code', function () { - it('should 404 on no error', function (done) { - request(createServer()) - .get('/') - .expect(404, done) + it('should ignore err.headers when not an object', function (done) { + request(createServer(createError('oops!', { + headers: 'foobar', + statusCode: 500 + }))) + .get('/') + .expect(500, done) + }) }) - it('should 500 on error', function (done) { - request(createServer(createError())) - .get('/') - .expect(500, done) - }) + describe('status code', function () { + it('should 404 on no error', function (done) { + request(createServer()) + .get('/') + .expect(404, done) + }) - it('should use err.statusCode', function (done) { - request(createServer(createError('nope', { - statusCode: 400 - }))) - .get('/') - .expect(400, done) - }) + it('should 500 on error', function (done) { + request(createServer(createError())) + .get('/') + .expect(500, done) + }) - it('should ignore non-error err.statusCode code', function (done) { - request(createServer(createError('created', { - statusCode: 201 - }))) - .get('/') - .expect(500, done) - }) + it('should use err.statusCode', function (done) { + request(createServer(createError('nope', { + statusCode: 400 + }))) + .get('/') + .expect(400, done) + }) - it('should ignore non-numeric err.statusCode', function (done) { - request(createServer(createError('oops', { - statusCode: 'oh no' - }))) - .get('/') - .expect(500, done) - }) + it('should ignore non-error err.statusCode code', function (done) { + request(createServer(createError('created', { + statusCode: 201 + }))) + .get('/') + .expect(500, done) + }) - it('should use err.status', function (done) { - request(createServer(createError('nope', { - status: 400 - }))) - .get('/') - .expect(400, done) - }) + it('should ignore non-numeric err.statusCode', function (done) { + request(createServer(createError('oops', { + statusCode: 'oh no' + }))) + .get('/') + .expect(500, done) + }) - it('should use err.status over err.statusCode', function (done) { - request(createServer(createError('nope', { - status: 400, - statusCode: 401 - }))) - .get('/') - .expect(400, done) - }) + it('should use err.status', function (done) { + request(createServer(createError('nope', { + status: 400 + }))) + .get('/') + .expect(400, done) + }) - it('should set status to 500 when err.status < 400', function (done) { - request(createServer(createError('oops', { - status: 202 - }))) - .get('/') - .expect(500, done) - }) + it('should use err.status over err.statusCode', function (done) { + request(createServer(createError('nope', { + status: 400, + statusCode: 401 + }))) + .get('/') + .expect(400, done) + }) - it('should set status to 500 when err.status > 599', function (done) { - request(createServer(createError('oops', { - status: 601 - }))) - .get('/') - .expect(500, done) - }) + it('should set status to 500 when err.status < 400', function (done) { + request(createServer(createError('oops', { + status: 202 + }))) + .get('/') + .expect(500, done) + }) - it('should use err.statusCode over invalid err.status', function (done) { - request(createServer(createError('nope', { - status: 50, - statusCode: 410 - }))) - .get('/') - .expect(410, done) - }) + it('should set status to 500 when err.status > 599', function (done) { + request(createServer(createError('oops', { + status: 601 + }))) + .get('/') + .expect(500, done) + }) - it('should ignore non-error err.status code', function (done) { - request(createServer(createError('created', { - status: 201 - }))) - .get('/') - .expect(500, done) - }) + it('should use err.statusCode over invalid err.status', function (done) { + request(createServer(createError('nope', { + status: 50, + statusCode: 410 + }))) + .get('/') + .expect(410, done) + }) - it('should ignore non-numeric err.status', function (done) { - request(createServer(createError('oops', { - status: 'oh no' - }))) - .get('/') - .expect(500, done) - }) - }) + it('should ignore non-error err.status code', function (done) { + request(createServer(createError('created', { + status: 201 + }))) + .get('/') + .expect(500, done) + }) - describeStatusMessage('status message', function () { - it('should be "Not Found" on no error', function (done) { - request(createServer()) - .get('/') - .expect(shouldHaveStatusMessage('Not Found')) - .expect(404, done) + it('should ignore non-numeric err.status', function (done) { + request(createServer(createError('oops', { + status: 'oh no' + }))) + .get('/') + .expect(500, done) + }) }) - it('should be "Internal Server Error" on error', function (done) { - request(createServer(createError())) - .get('/') - .expect(shouldHaveStatusMessage('Internal Server Error')) - .expect(500, done) - }) + describeStatusMessage('status message', function () { + it('should be "Not Found" on no error', function (done) { + request(createServer()) + .get('/') + .expect(shouldHaveStatusMessage('Not Found')) + .expect(404, done) + }) - it('should be "Bad Request" when err.statusCode = 400', function (done) { - request(createServer(createError('oops', { - status: 400 - }))) - .get('/') - .expect(shouldHaveStatusMessage('Bad Request')) - .expect(400, done) - }) + it('should be "Internal Server Error" on error', function (done) { + request(createServer(createError())) + .get('/') + .expect(shouldHaveStatusMessage('Internal Server Error')) + .expect(500, done) + }) - it('should reset existing res.statusMessage', function (done) { - function onRequest (req, res, next) { - res.statusMessage = 'An Error Occurred' - next(new Error()) - } + it('should be "Bad Request" when err.statusCode = 400', function (done) { + request(createServer(createError('oops', { + status: 400 + }))) + .get('/') + .expect(shouldHaveStatusMessage('Bad Request')) + .expect(400, done) + }) - request(createServer(onRequest)) - .get('/') - .expect(shouldHaveStatusMessage('Internal Server Error')) - .expect(500, done) - }) - }) + it('should reset existing res.statusMessage', function (done) { + function onRequest (req, res, next) { + res.statusMessage = 'An Error Occurred' + next(new Error()) + } - describe('404 response', function () { - it('should include method and pathname', function (done) { - request(createServer()) - .get('/foo') - .expect(404, /
Cannot GET \/foo<\/pre>/, done)
+        request(createServer(onRequest))
+          .get('/')
+          .expect(shouldHaveStatusMessage('Internal Server Error'))
+          .expect(500, done)
+      })
     })
 
-    it('should escape method and pathname characters', function (done) {
-      rawrequest(createServer())
-        .get('/')
-        .expect(404, /
Cannot GET \/%3Cla'me%3E<\/pre>/, done)
-    })
+    describe('404 response', function () {
+      it('should include method and pathname', function (done) {
+        request(createServer())
+          .get('/foo')
+          .expect(404, /
Cannot GET \/foo<\/pre>/, done)
+      })
 
-    it('should fallback to generic pathname without URL', function (done) {
-      var server = createServer(function (req, res, next) {
-        req.url = undefined
-        next()
+      it('should escape method and pathname characters', function (done) {
+        rawrequest(createServer())
+          .get('/')
+          .expect(404, /
Cannot GET \/%3Cla'me%3E<\/pre>/, done)
       })
 
-      request(server)
-        .get('/foo')
-        .expect(404, /
Cannot GET resource<\/pre>/, done)
-    })
+      it('should fallback to generic pathname without URL', function (done) {
+        var server = createServer(function (req, res, next) {
+          req.url = undefined
+          next()
+        })
 
-    it('should include original pathname', function (done) {
-      var server = createServer(function (req, res, next) {
-        var parts = req.url.split('/')
-        req.originalUrl = req.url
-        req.url = '/' + parts.slice(2).join('/')
-        next()
+        request(server)
+          .get('/foo')
+          .expect(404, /
Cannot GET resource<\/pre>/, done)
       })
 
-      request(server)
-        .get('/foo/bar')
-        .expect(404, /
Cannot GET \/foo\/bar<\/pre>/, done)
-    })
+      it('should include original pathname', function (done) {
+        var server = createServer(function (req, res, next) {
+          var parts = req.url.split('/')
+          req.originalUrl = req.url
+          req.url = '/' + parts.slice(2).join('/')
+          next()
+        })
 
-    it('should include pathname only', function (done) {
-      rawrequest(createServer())
-        .get('http://localhost/foo?bar=1')
-        .expect(404, /
Cannot GET \/foo<\/pre>/, done)
-    })
+        request(server)
+          .get('/foo/bar')
+          .expect(404, /
Cannot GET \/foo\/bar<\/pre>/, done)
+      })
 
-    it('should handle HEAD', function (done) {
-      request(createServer())
-        .head('/foo')
-        .expect(404)
-        .expect(shouldNotHaveBody())
-        .end(done)
-    })
+      it('should include pathname only', function (done) {
+        rawrequest(createServer())
+          .get('http://localhost/foo?bar=1')
+          .expect(404, /
Cannot GET \/foo<\/pre>/, done)
+      })
 
-    it('should include X-Content-Type-Options header', function (done) {
-      request(createServer())
-        .get('/foo')
-        .expect('X-Content-Type-Options', 'nosniff')
-        .expect(404, done)
-    })
+      it('should handle HEAD', function (done) {
+        request(createServer())
+          .head('/foo')
+          .expect(404)
+          .expect(shouldNotHaveBody())
+          .end(done)
+      })
 
-    it('should include Content-Security-Policy header', function (done) {
-      request(createServer())
-        .get('/foo')
-        .expect('Content-Security-Policy', "default-src 'none'")
-        .expect(404, done)
-    })
+      it('should include X-Content-Type-Options header', function (done) {
+        request(createServer())
+          .get('/foo')
+          .expect('X-Content-Type-Options', 'nosniff')
+          .expect(404, done)
+      })
 
-    it('should not hang/error if there is a request body', function (done) {
-      var buf = Buffer.alloc(1024 * 16, '.')
-      var server = createServer()
-      var test = request(server).post('/foo')
-      test.write(buf)
-      test.write(buf)
-      test.write(buf)
-      test.expect(404, done)
-    })
-  })
+      it('should include Content-Security-Policy header', function (done) {
+        request(createServer())
+          .get('/foo')
+          .expect('Content-Security-Policy', "default-src 'none'")
+          .expect(404, done)
+      })
 
-  describe('error response', function () {
-    it('should include error stack', function (done) {
-      request(createServer(createError('boom!')))
-        .get('/foo')
-        .expect(500, /
Error: boom!
   at/, done) + it('should not hang/error if there is a request body', function (done) { + var buf = Buffer.alloc(1024 * 16, '.') + var server = createServer() + var test = request(server).post('/foo') + test.write(buf) + test.write(buf) + test.write(buf) + test.expect(404, done) + }) }) - it('should handle HEAD', function (done) { - request(createServer(createError('boom!'))) - .head('/foo') - .expect(500) - .expect(shouldNotHaveBody()) - .end(done) - }) + describe('error response', function () { + it('should include error stack', function (done) { + request(createServer(createError('boom!'))) + .get('/foo') + .expect(500, /
Error: boom!
   at/, done) + }) - it('should include X-Content-Type-Options header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') - .expect('X-Content-Type-Options', 'nosniff') - .expect(500, done) - }) + it('should handle HEAD', function (done) { + request(createServer(createError('boom!'))) + .head('/foo') + .expect(500) + .expect(shouldNotHaveBody()) + .end(done) + }) - it('should includeContent-Security-Policy header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') - .expect('Content-Security-Policy', "default-src 'none'") - .expect(500, done) - }) + it('should include X-Content-Type-Options header', function (done) { + request(createServer(createError('boom!'))) + .get('/foo') + .expect('X-Content-Type-Options', 'nosniff') + .expect(500, done) + }) - it('should handle non-error-objects', function (done) { - request(createServer('lame string')) - .get('/foo') - .expect(500, /
lame string<\/pre>/, done)
-    })
+      it('should includeContent-Security-Policy header', function (done) {
+        request(createServer(createError('boom!')))
+          .get('/foo')
+          .expect('Content-Security-Policy', "default-src 'none'")
+          .expect(500, done)
+      })
 
-    it('should handle null prototype objects', function (done) {
-      request(createServer(Object.create(null)))
-        .get('/foo')
-        .expect(500, /
Internal Server Error<\/pre>/, done)
-    })
+      it('should handle non-error-objects', function (done) {
+        request(createServer('lame string'))
+          .get('/foo')
+          .expect(500, /
lame string<\/pre>/, done)
+      })
 
-    it('should send staus code name when production', function (done) {
-      var err = createError('boom!', {
-        status: 501
+      it('should handle null prototype objects', function (done) {
+        request(createServer(Object.create(null)))
+          .get('/foo')
+          .expect(500, /
Internal Server Error<\/pre>/, done)
       })
-      request(createServer(err, {
-        env: 'production'
-      }))
-        .get('/foo')
-        .expect(501, /
Not Implemented<\/pre>/, done)
-    })
 
-    describe('when there is a request body', function () {
-      it('should not hang/error when unread', function (done) {
-        var buf = Buffer.alloc(1024 * 16, '.')
-        var server = createServer(new Error('boom!'))
-        var test = request(server).post('/foo')
-        test.write(buf)
-        test.write(buf)
-        test.write(buf)
-        test.expect(500, done)
+      it('should send staus code name when production', function (done) {
+        var err = createError('boom!', {
+          status: 501
+        })
+        request(createServer(err, {
+          env: 'production'
+        }))
+          .get('/foo')
+          .expect(501, /
Not Implemented<\/pre>/, done)
       })
 
-      it('should not hang/error when actively piped', function (done) {
-        var buf = Buffer.alloc(1024 * 16, '.')
-        var server = createServer(function (req, res, next) {
-          req.pipe(stream)
-          process.nextTick(function () {
-            next(new Error('boom!'))
+      describe('when there is a request body', function () {
+        it('should not hang/error when unread', function (done) {
+          var buf = Buffer.alloc(1024 * 16, '.')
+          var server = createServer(new Error('boom!'))
+          var test = request(server).post('/foo')
+          test.write(buf)
+          test.write(buf)
+          test.write(buf)
+          test.expect(500, done)
+        })
+
+        it('should not hang/error when actively piped', function (done) {
+          var buf = Buffer.alloc(1024 * 16, '.')
+          var server = createServer(function (req, res, next) {
+            req.pipe(stream)
+            process.nextTick(function () {
+              next(new Error('boom!'))
+            })
           })
+          var stream = createSlowWriteStream()
+          var test = request(server).post('/foo')
+          test.write(buf)
+          test.write(buf)
+          test.write(buf)
+          test.expect(500, done)
+        })
+
+        it('should not hang/error when read', function (done) {
+          var buf = Buffer.alloc(1024 * 16, '.')
+          var server = createServer(function (req, res, next) {
+            // read off the request
+            req.once('end', function () {
+              next(new Error('boom!'))
+            })
+            req.resume()
+          })
+          var test = request(server).post('/foo')
+          test.write(buf)
+          test.write(buf)
+          test.write(buf)
+          test.expect(500, done)
         })
-        var stream = createSlowWriteStream()
-        var test = request(server).post('/foo')
-        test.write(buf)
-        test.write(buf)
-        test.write(buf)
-        test.expect(500, done)
       })
 
-      it('should not hang/error when read', function (done) {
-        var buf = Buffer.alloc(1024 * 16, '.')
-        var server = createServer(function (req, res, next) {
-          // read off the request
-          req.once('end', function () {
-            next(new Error('boom!'))
+      describe('when res.statusCode set', function () {
+        it('should keep when >= 400', function (done) {
+          var server = createServer(function (req, res) {
+            var done = finalhandler(req, res)
+            res.statusCode = 503
+            done(new Error('oops'))
           })
-          req.resume()
+
+          request(server)
+            .get('/foo')
+            .expect(503, done)
+        })
+
+        it('should convert to 500 is not a number', function (done) {
+          var server = createServer(function (req, res) {
+            var done = finalhandler(req, res)
+            res.statusCode = 'oh no'
+            done(new Error('oops'))
+          })
+
+          request(server)
+            .get('/foo')
+            .expect(500, done)
+        })
+
+        it('should override with err.status', function (done) {
+          var server = createServer(function (req, res) {
+            var done = finalhandler(req, res)
+            var err = createError('oops', {
+              status: 414,
+              statusCode: 503
+            })
+            done(err)
+          })
+
+          request(server)
+            .get('/foo')
+            .expect(414, done)
+        })
+
+        it('should default body to status message in production', function (done) {
+          var err = createError('boom!', {
+            status: 509
+          })
+          request(createServer(err, {
+            env: 'production'
+          }))
+            .get('/foo')
+            .expect(509, /
Bandwidth Limit Exceeded<\/pre>/, done)
+        })
+      })
+
+      describe('when res.statusCode undefined', function () {
+        it('should set to 500', function (done) {
+          var server = createServer(function (req, res) {
+            var done = finalhandler(req, res)
+            res.statusCode = undefined
+            done(new Error('oops'))
+          })
+
+          request(server)
+            .get('/foo')
+            .expect(500, done)
         })
-        var test = request(server).post('/foo')
-        test.write(buf)
-        test.write(buf)
-        test.write(buf)
-        test.expect(500, done)
       })
     })
 
-    describe('when res.statusCode set', function () {
-      it('should keep when >= 400', function (done) {
-        var server = http.createServer(function (req, res) {
+    describe('headers set', function () {
+      it('should persist set headers', function (done) {
+        var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.statusCode = 503
-          done(new Error('oops'))
+          res.setHeader('Server', 'foobar')
+          done()
         })
 
         request(server)
           .get('/foo')
-          .expect(503, done)
+          .expect(404)
+          .expect('Server', 'foobar')
+          .end(done)
       })
 
-      it('should convert to 500 is not a number', function (done) {
-        var server = http.createServer(function (req, res) {
+      it('should override content-type and length', function (done) {
+        var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.statusCode = 'oh no'
-          done(new Error('oops'))
+          res.setHeader('Content-Type', 'image/png')
+          res.setHeader('Content-Length', '50')
+          done()
         })
 
         request(server)
           .get('/foo')
-          .expect(500, done)
+          .expect(404)
+          .expect('Content-Type', 'text/html; charset=utf-8')
+          .expect('Content-Length', '142')
+          .end(done)
       })
 
-      it('should override with err.status', function (done) {
-        var server = http.createServer(function (req, res) {
+      it('should remove other content headers', function (done) {
+        var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          var err = createError('oops', {
-            status: 414,
-            statusCode: 503
-          })
-          done(err)
+          res.setHeader('Content-Encoding', 'gzip')
+          res.setHeader('Content-Language', 'jp')
+          res.setHeader('Content-Range', 'bytes 0-2/10')
+          done()
         })
 
         request(server)
           .get('/foo')
-          .expect(414, done)
+          .expect(404)
+          .expect(shouldNotHaveHeader('Content-Encoding'))
+          .expect(shouldNotHaveHeader('Content-Language'))
+          .expect(shouldNotHaveHeader('Content-Range'))
+          .end(done)
       })
+    })
 
-      it('should default body to status message in production', function (done) {
-        var err = createError('boom!', {
-          status: 509
+    describe('request started', function () {
+      it('should not respond', function (done) {
+        var server = createServer(function (req, res) {
+          var done = finalhandler(req, res)
+          res.statusCode = 301
+          res.write('0')
+          process.nextTick(function () {
+            done()
+            res.end('1')
+          })
         })
-        request(createServer(err, {
-          env: 'production'
-        }))
+
+        request(server)
           .get('/foo')
-          .expect(509, /
Bandwidth Limit Exceeded<\/pre>/, done)
+          .expect(301, '01', done)
       })
-    })
 
-    describe('when res.statusCode undefined', function () {
-      it('should set to 500', function (done) {
-        var server = http.createServer(function (req, res) {
+      it('should terminate on error', function (done) {
+        var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.statusCode = undefined
-          done(new Error('oops'))
+          res.statusCode = 301
+          res.write('0')
+          process.nextTick(function () {
+            done(createError('too many requests', {
+              status: 429,
+              headers: { 'Retry-After': '5' }
+            }))
+            res.end('1')
+          })
         })
 
         request(server)
           .get('/foo')
-          .expect(500, done)
+          .on('request', function onrequest (test) {
+            test.req.on('response', function onresponse (res) {
+              if (res.listeners('error').length > 0) {
+                // forward aborts as errors for supertest
+                res.on('aborted', function onabort () {
+                  res.emit('error', new Error('aborted'))
+                })
+              }
+            })
+          })
+          .end(function (err) {
+            if (err && err.message !== 'aborted') return done(err)
+            assert.strictEqual(this.res.statusCode, 301)
+            assert.strictEqual(this.res.text, '0')
+            done()
+          })
       })
     })
-  })
 
-  describe('headers set', function () {
-    it('should persist set headers', function (done) {
-      var server = http.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        res.setHeader('Server', 'foobar')
-        done()
-      })
+    describe('onerror', function () {
+      it('should be invoked when error', function (done) {
+        var err = new Error('boom!')
+        var error
 
-      request(server)
-        .get('/foo')
-        .expect(404)
-        .expect('Server', 'foobar')
-        .end(done)
-    })
+        function log (e) {
+          error = e
+        }
 
-    it('should override content-type and length', function (done) {
-      var server = http.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        res.setHeader('Content-Type', 'image/png')
-        res.setHeader('Content-Length', '50')
-        done()
+        request(createServer(err, { onerror: log }))
+          .get('/')
+          .end(function () {
+            assert.equal(error, err)
+            done()
+          })
       })
-
-      request(server)
-        .get('/foo')
-        .expect(404)
-        .expect('Content-Type', 'text/html; charset=utf-8')
-        .expect('Content-Length', '142')
-        .end(done)
     })
 
-    it('should remove other content headers', function (done) {
-      var server = http.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        res.setHeader('Content-Encoding', 'gzip')
-        res.setHeader('Content-Language', 'jp')
-        res.setHeader('Content-Range', 'bytes 0-2/10')
-        done()
-      })
-
-      request(server)
-        .get('/foo')
-        .expect(404)
-        .expect(shouldNotHaveHeader('Content-Encoding'))
-        .expect(shouldNotHaveHeader('Content-Language'))
-        .expect(shouldNotHaveHeader('Content-Range'))
-        .end(done)
-    })
-  })
+    describe('no deprecation warnings', function () {
+      it('should respond 404 on no error', function (done) {
+        var http2
+        try {
+          http2 = require('http2')
+        } catch (e) {
+          return done()
+        }
 
-  describe('request started', function () {
-    it('should not respond', function (done) {
-      var server = http.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        res.statusCode = 301
-        res.write('0')
-        process.nextTick(function () {
+        var warned = false
+
+        process.once('warning', function (warning) {
+          assert.fail(warning)
+        })
+
+        var server = http2.createServer(function (req, res) {
+          var done = finalhandler(req, res)
           done()
-          res.end('1')
         })
-      })
 
-      request(server)
-        .get('/foo')
-        .expect(301, '01', done)
-    })
+        server.listen(function () {
+          var port = server.address().port
+          var client = http2.connect('http://localhost:' + port)
+          var req = client.request({
+            ':method': 'GET',
+            ':path': '/foo'
+          })
 
-    it('should terminate on error', function (done) {
-      var server = http.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        res.statusCode = 301
-        res.write('0')
-        process.nextTick(function () {
-          done(createError('too many requests', {
-            status: 429,
-            headers: { 'Retry-After': '5' }
-          }))
-          res.end('1')
+          req.on('response', function (headers) {
+            assert.strictEqual(headers[':status'], 404)
+            req.close()
+            client.close()
+            server.close()
+            assert.strictEqual(warned, false)
+            done()
+          })
         })
       })
 
-      request(server)
-        .get('/foo')
-        .on('request', function onrequest (test) {
-          test.req.on('response', function onresponse (res) {
-            if (res.listeners('error').length > 0) {
-              // forward aborts as errors for supertest
-              res.on('aborted', function onabort () {
-                res.emit('error', new Error('aborted'))
-              })
-            }
-          })
-        })
-        .end(function (err) {
-          if (err && err.message !== 'aborted') return done(err)
-          assert.strictEqual(this.res.statusCode, 301)
-          assert.strictEqual(this.res.text, '0')
-          done()
+      it('should respond 500 on error', function (done) {
+        var http2
+        try {
+          http2 = require('http2')
+        } catch (e) {
+          return done()
+        }
+
+        var warned = false
+
+        process.once('warning', function (warning) {
+          assert.fail(warning)
         })
-    })
-  })
 
-  describe('onerror', function () {
-    it('should be invoked when error', function (done) {
-      var err = new Error('boom!')
-      var error
+        var err = createError()
 
-      function log (e) {
-        error = e
-      }
+        var server = http2.createServer(function (req, res) {
+          var done = finalhandler(req, res)
 
-      request(createServer(err, { onerror: log }))
-        .get('/')
-        .end(function () {
-          assert.equal(error, err)
-          done()
+          if (typeof err === 'function') {
+            err(req, res, done)
+            return
+          }
+
+          done(err)
         })
+
+        server.listen(function () {
+          var port = server.address().port
+          var client = http2.connect('http://localhost:' + port)
+          var req = client.request({
+            ':method': 'GET',
+            ':path': '/foo'
+          })
+
+          req.on('response', function (headers) {
+            assert.strictEqual(headers[':status'], 500)
+            req.close()
+            client.close()
+            server.close()
+            assert.strictEqual(warned, false)
+            done()
+          })
+        })
+      })
     })
   })
-})
+}

From da590215fe028467a0211318bb4bf3c23a24f974 Mon Sep 17 00:00:00 2001
From: "alexander.akait" 
Date: Mon, 19 Aug 2024 19:30:22 +0300
Subject: [PATCH 2/6] test: fix

---
 test/test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/test.js b/test/test.js
index 61e4658..74cd922 100644
--- a/test/test.js
+++ b/test/test.js
@@ -28,7 +28,7 @@ for (var i = 0; i < servers.length; i++) {
   const name = servers[i][0]
   const createServer = servers[i][1]
 
-  describe(name, () => {
+  describe(name, function () {
     describe('headers', function () {
       it('should ignore err.headers without status code', function (done) {
         request(createServer(createError('oops!', {

From bd8c04ab1e89fa42ada1dbaa2d6acb545976fbbf Mon Sep 17 00:00:00 2001
From: "alexander.akait" 
Date: Mon, 19 Aug 2024 19:47:11 +0300
Subject: [PATCH 3/6] test: fix node@9

---
 test/test.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/test.js b/test/test.js
index 74cd922..f45d3d5 100644
--- a/test/test.js
+++ b/test/test.js
@@ -594,6 +594,7 @@ for (var i = 0; i < servers.length; i++) {
         var warned = false
 
         process.once('warning', function (warning) {
+          if (/The http2 module is an experimental API/.test(warning)) return
           assert.fail(warning)
         })
 
@@ -632,6 +633,7 @@ for (var i = 0; i < servers.length; i++) {
         var warned = false
 
         process.once('warning', function (warning) {
+          if (/The http2 module is an experimental API/.test(warning)) return
           assert.fail(warning)
         })
 

From 7795a8cfbd03cb904e40f6fc9afb4372e3a32f11 Mon Sep 17 00:00:00 2001
From: "alexander.akait" 
Date: Tue, 20 Aug 2024 15:08:51 +0300
Subject: [PATCH 4/6] refactor: tests

---
 test/test.js | 1053 +++++++++++++++++++++++++-------------------------
 1 file changed, 527 insertions(+), 526 deletions(-)

diff --git a/test/test.js b/test/test.js
index f45d3d5..a5e25dd 100644
--- a/test/test.js
+++ b/test/test.js
@@ -19,655 +19,656 @@ var describeStatusMessage = !/statusMessage/.test(http.IncomingMessage.toString(
   ? describe.skip
   : describe
 
-const servers = [
-  ['http', createHTTPServer],
-  ['http2', createHTTP2Server]
-]
+var topDescribe = function (createServer) {
+  describe('headers', function () {
+    it('should ignore err.headers without status code', function (done) {
+      request(createServer(createError('oops!', {
+        headers: { 'X-Custom-Header': 'foo' }
+      })))
+        .get('/')
+        .expect(shouldNotHaveHeader('X-Custom-Header'))
+        .expect(500, done)
+    })
 
-for (var i = 0; i < servers.length; i++) {
-  const name = servers[i][0]
-  const createServer = servers[i][1]
-
-  describe(name, function () {
-    describe('headers', function () {
-      it('should ignore err.headers without status code', function (done) {
-        request(createServer(createError('oops!', {
-          headers: { 'X-Custom-Header': 'foo' }
-        })))
-          .get('/')
-          .expect(shouldNotHaveHeader('X-Custom-Header'))
-          .expect(500, done)
-      })
+    it('should ignore err.headers with invalid res.status', function (done) {
+      request(createServer(createError('oops!', {
+        headers: { 'X-Custom-Header': 'foo' },
+        status: 601
+      })))
+        .get('/')
+        .expect(shouldNotHaveHeader('X-Custom-Header'))
+        .expect(500, done)
+    })
 
-      it('should ignore err.headers with invalid res.status', function (done) {
-        request(createServer(createError('oops!', {
-          headers: { 'X-Custom-Header': 'foo' },
-          status: 601
-        })))
-          .get('/')
-          .expect(shouldNotHaveHeader('X-Custom-Header'))
-          .expect(500, done)
-      })
+    it('should ignore err.headers with invalid res.statusCode', function (done) {
+      request(createServer(createError('oops!', {
+        headers: { 'X-Custom-Header': 'foo' },
+        statusCode: 601
+      })))
+        .get('/')
+        .expect(shouldNotHaveHeader('X-Custom-Header'))
+        .expect(500, done)
+    })
 
-      it('should ignore err.headers with invalid res.statusCode', function (done) {
-        request(createServer(createError('oops!', {
-          headers: { 'X-Custom-Header': 'foo' },
-          statusCode: 601
-        })))
-          .get('/')
-          .expect(shouldNotHaveHeader('X-Custom-Header'))
-          .expect(500, done)
-      })
+    it('should include err.headers with err.status', function (done) {
+      request(createServer(createError('oops!', {
+        headers: { 'X-Custom-Header': 'foo=500', 'X-Custom-Header2': 'bar' },
+        status: 500
+      })))
+        .get('/')
+        .expect('X-Custom-Header', 'foo=500')
+        .expect('X-Custom-Header2', 'bar')
+        .expect(500, done)
+    })
 
-      it('should include err.headers with err.status', function (done) {
-        request(createServer(createError('oops!', {
-          headers: { 'X-Custom-Header': 'foo=500', 'X-Custom-Header2': 'bar' },
-          status: 500
-        })))
-          .get('/')
-          .expect('X-Custom-Header', 'foo=500')
-          .expect('X-Custom-Header2', 'bar')
-          .expect(500, done)
-      })
+    it('should include err.headers with err.statusCode', function (done) {
+      request(createServer(createError('too many requests', {
+        headers: { 'Retry-After': '5' },
+        statusCode: 429
+      })))
+        .get('/')
+        .expect('Retry-After', '5')
+        .expect(429, done)
+    })
 
-      it('should include err.headers with err.statusCode', function (done) {
-        request(createServer(createError('too many requests', {
-          headers: { 'Retry-After': '5' },
-          statusCode: 429
-        })))
-          .get('/')
-          .expect('Retry-After', '5')
-          .expect(429, done)
-      })
+    it('should ignore err.headers when not an object', function (done) {
+      request(createServer(createError('oops!', {
+        headers: 'foobar',
+        statusCode: 500
+      })))
+        .get('/')
+        .expect(500, done)
+    })
+  })
 
-      it('should ignore err.headers when not an object', function (done) {
-        request(createServer(createError('oops!', {
-          headers: 'foobar',
-          statusCode: 500
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+  describe('status code', function () {
+    it('should 404 on no error', function (done) {
+      request(createServer())
+        .get('/')
+        .expect(404, done)
     })
 
-    describe('status code', function () {
-      it('should 404 on no error', function (done) {
-        request(createServer())
-          .get('/')
-          .expect(404, done)
-      })
+    it('should 500 on error', function (done) {
+      request(createServer(createError()))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should 500 on error', function (done) {
-        request(createServer(createError()))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should use err.statusCode', function (done) {
+      request(createServer(createError('nope', {
+        statusCode: 400
+      })))
+        .get('/')
+        .expect(400, done)
+    })
 
-      it('should use err.statusCode', function (done) {
-        request(createServer(createError('nope', {
-          statusCode: 400
-        })))
-          .get('/')
-          .expect(400, done)
-      })
+    it('should ignore non-error err.statusCode code', function (done) {
+      request(createServer(createError('created', {
+        statusCode: 201
+      })))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should ignore non-error err.statusCode code', function (done) {
-        request(createServer(createError('created', {
-          statusCode: 201
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should ignore non-numeric err.statusCode', function (done) {
+      request(createServer(createError('oops', {
+        statusCode: 'oh no'
+      })))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should ignore non-numeric err.statusCode', function (done) {
-        request(createServer(createError('oops', {
-          statusCode: 'oh no'
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should use err.status', function (done) {
+      request(createServer(createError('nope', {
+        status: 400
+      })))
+        .get('/')
+        .expect(400, done)
+    })
 
-      it('should use err.status', function (done) {
-        request(createServer(createError('nope', {
-          status: 400
-        })))
-          .get('/')
-          .expect(400, done)
-      })
+    it('should use err.status over err.statusCode', function (done) {
+      request(createServer(createError('nope', {
+        status: 400,
+        statusCode: 401
+      })))
+        .get('/')
+        .expect(400, done)
+    })
 
-      it('should use err.status over err.statusCode', function (done) {
-        request(createServer(createError('nope', {
-          status: 400,
-          statusCode: 401
-        })))
-          .get('/')
-          .expect(400, done)
-      })
+    it('should set status to 500 when err.status < 400', function (done) {
+      request(createServer(createError('oops', {
+        status: 202
+      })))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should set status to 500 when err.status < 400', function (done) {
-        request(createServer(createError('oops', {
-          status: 202
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should set status to 500 when err.status > 599', function (done) {
+      request(createServer(createError('oops', {
+        status: 601
+      })))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should set status to 500 when err.status > 599', function (done) {
-        request(createServer(createError('oops', {
-          status: 601
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should use err.statusCode over invalid err.status', function (done) {
+      request(createServer(createError('nope', {
+        status: 50,
+        statusCode: 410
+      })))
+        .get('/')
+        .expect(410, done)
+    })
 
-      it('should use err.statusCode over invalid err.status', function (done) {
-        request(createServer(createError('nope', {
-          status: 50,
-          statusCode: 410
-        })))
-          .get('/')
-          .expect(410, done)
-      })
+    it('should ignore non-error err.status code', function (done) {
+      request(createServer(createError('created', {
+        status: 201
+      })))
+        .get('/')
+        .expect(500, done)
+    })
 
-      it('should ignore non-error err.status code', function (done) {
-        request(createServer(createError('created', {
-          status: 201
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+    it('should ignore non-numeric err.status', function (done) {
+      request(createServer(createError('oops', {
+        status: 'oh no'
+      })))
+        .get('/')
+        .expect(500, done)
+    })
+  })
 
-      it('should ignore non-numeric err.status', function (done) {
-        request(createServer(createError('oops', {
-          status: 'oh no'
-        })))
-          .get('/')
-          .expect(500, done)
-      })
+  describeStatusMessage('status message', function () {
+    it('should be "Not Found" on no error', function (done) {
+      request(createServer())
+        .get('/')
+        .expect(shouldHaveStatusMessage('Not Found'))
+        .expect(404, done)
     })
 
-    describeStatusMessage('status message', function () {
-      it('should be "Not Found" on no error', function (done) {
-        request(createServer())
-          .get('/')
-          .expect(shouldHaveStatusMessage('Not Found'))
-          .expect(404, done)
-      })
+    it('should be "Internal Server Error" on error', function (done) {
+      request(createServer(createError()))
+        .get('/')
+        .expect(shouldHaveStatusMessage('Internal Server Error'))
+        .expect(500, done)
+    })
 
-      it('should be "Internal Server Error" on error', function (done) {
-        request(createServer(createError()))
-          .get('/')
-          .expect(shouldHaveStatusMessage('Internal Server Error'))
-          .expect(500, done)
-      })
+    it('should be "Bad Request" when err.statusCode = 400', function (done) {
+      request(createServer(createError('oops', {
+        status: 400
+      })))
+        .get('/')
+        .expect(shouldHaveStatusMessage('Bad Request'))
+        .expect(400, done)
+    })
 
-      it('should be "Bad Request" when err.statusCode = 400', function (done) {
-        request(createServer(createError('oops', {
-          status: 400
-        })))
-          .get('/')
-          .expect(shouldHaveStatusMessage('Bad Request'))
-          .expect(400, done)
-      })
+    it('should reset existing res.statusMessage', function (done) {
+      function onRequest (req, res, next) {
+        res.statusMessage = 'An Error Occurred'
+        next(new Error())
+      }
 
-      it('should reset existing res.statusMessage', function (done) {
-        function onRequest (req, res, next) {
-          res.statusMessage = 'An Error Occurred'
-          next(new Error())
-        }
+      request(createServer(onRequest))
+        .get('/')
+        .expect(shouldHaveStatusMessage('Internal Server Error'))
+        .expect(500, done)
+    })
+  })
 
-        request(createServer(onRequest))
-          .get('/')
-          .expect(shouldHaveStatusMessage('Internal Server Error'))
-          .expect(500, done)
-      })
+  describe('404 response', function () {
+    it('should include method and pathname', function (done) {
+      request(createServer())
+        .get('/foo')
+        .expect(404, /
Cannot GET \/foo<\/pre>/, done)
     })
 
-    describe('404 response', function () {
-      it('should include method and pathname', function (done) {
-        request(createServer())
-          .get('/foo')
-          .expect(404, /
Cannot GET \/foo<\/pre>/, done)
-      })
+    it('should escape method and pathname characters', function (done) {
+      rawrequest(createServer())
+        .get('/')
+        .expect(404, /
Cannot GET \/%3Cla'me%3E<\/pre>/, done)
+    })
 
-      it('should escape method and pathname characters', function (done) {
-        rawrequest(createServer())
-          .get('/')
-          .expect(404, /
Cannot GET \/%3Cla'me%3E<\/pre>/, done)
+    it('should fallback to generic pathname without URL', function (done) {
+      var server = createServer(function (req, res, next) {
+        req.url = undefined
+        next()
       })
 
-      it('should fallback to generic pathname without URL', function (done) {
-        var server = createServer(function (req, res, next) {
-          req.url = undefined
-          next()
-        })
+      request(server)
+        .get('/foo')
+        .expect(404, /
Cannot GET resource<\/pre>/, done)
+    })
 
-        request(server)
-          .get('/foo')
-          .expect(404, /
Cannot GET resource<\/pre>/, done)
+    it('should include original pathname', function (done) {
+      var server = createServer(function (req, res, next) {
+        var parts = req.url.split('/')
+        req.originalUrl = req.url
+        req.url = '/' + parts.slice(2).join('/')
+        next()
       })
 
-      it('should include original pathname', function (done) {
-        var server = createServer(function (req, res, next) {
-          var parts = req.url.split('/')
-          req.originalUrl = req.url
-          req.url = '/' + parts.slice(2).join('/')
-          next()
-        })
-
-        request(server)
-          .get('/foo/bar')
-          .expect(404, /
Cannot GET \/foo\/bar<\/pre>/, done)
-      })
+      request(server)
+        .get('/foo/bar')
+        .expect(404, /
Cannot GET \/foo\/bar<\/pre>/, done)
+    })
 
-      it('should include pathname only', function (done) {
-        rawrequest(createServer())
-          .get('http://localhost/foo?bar=1')
-          .expect(404, /
Cannot GET \/foo<\/pre>/, done)
-      })
+    it('should include pathname only', function (done) {
+      rawrequest(createServer())
+        .get('http://localhost/foo?bar=1')
+        .expect(404, /
Cannot GET \/foo<\/pre>/, done)
+    })
 
-      it('should handle HEAD', function (done) {
-        request(createServer())
-          .head('/foo')
-          .expect(404)
-          .expect(shouldNotHaveBody())
-          .end(done)
-      })
+    it('should handle HEAD', function (done) {
+      request(createServer())
+        .head('/foo')
+        .expect(404)
+        .expect(shouldNotHaveBody())
+        .end(done)
+    })
 
-      it('should include X-Content-Type-Options header', function (done) {
-        request(createServer())
-          .get('/foo')
-          .expect('X-Content-Type-Options', 'nosniff')
-          .expect(404, done)
-      })
+    it('should include X-Content-Type-Options header', function (done) {
+      request(createServer())
+        .get('/foo')
+        .expect('X-Content-Type-Options', 'nosniff')
+        .expect(404, done)
+    })
 
-      it('should include Content-Security-Policy header', function (done) {
-        request(createServer())
-          .get('/foo')
-          .expect('Content-Security-Policy', "default-src 'none'")
-          .expect(404, done)
-      })
+    it('should include Content-Security-Policy header', function (done) {
+      request(createServer())
+        .get('/foo')
+        .expect('Content-Security-Policy', "default-src 'none'")
+        .expect(404, done)
+    })
 
-      it('should not hang/error if there is a request body', function (done) {
-        var buf = Buffer.alloc(1024 * 16, '.')
-        var server = createServer()
-        var test = request(server).post('/foo')
-        test.write(buf)
-        test.write(buf)
-        test.write(buf)
-        test.expect(404, done)
-      })
+    it('should not hang/error if there is a request body', function (done) {
+      var buf = Buffer.alloc(1024 * 16, '.')
+      var server = createServer()
+      var test = request(server).post('/foo')
+      test.write(buf)
+      test.write(buf)
+      test.write(buf)
+      test.expect(404, done)
     })
+  })
 
-    describe('error response', function () {
-      it('should include error stack', function (done) {
-        request(createServer(createError('boom!')))
-          .get('/foo')
-          .expect(500, /
Error: boom!
   at/, done) - }) + describe('error response', function () { + it('should include error stack', function (done) { + request(createServer(createError('boom!'))) + .get('/foo') + .expect(500, /
Error: boom!
   at/, done) + }) - it('should handle HEAD', function (done) { - request(createServer(createError('boom!'))) - .head('/foo') - .expect(500) - .expect(shouldNotHaveBody()) - .end(done) - }) + it('should handle HEAD', function (done) { + request(createServer(createError('boom!'))) + .head('/foo') + .expect(500) + .expect(shouldNotHaveBody()) + .end(done) + }) - it('should include X-Content-Type-Options header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') - .expect('X-Content-Type-Options', 'nosniff') - .expect(500, done) - }) + it('should include X-Content-Type-Options header', function (done) { + request(createServer(createError('boom!'))) + .get('/foo') + .expect('X-Content-Type-Options', 'nosniff') + .expect(500, done) + }) - it('should includeContent-Security-Policy header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') - .expect('Content-Security-Policy', "default-src 'none'") - .expect(500, done) - }) + it('should includeContent-Security-Policy header', function (done) { + request(createServer(createError('boom!'))) + .get('/foo') + .expect('Content-Security-Policy', "default-src 'none'") + .expect(500, done) + }) - it('should handle non-error-objects', function (done) { - request(createServer('lame string')) - .get('/foo') - .expect(500, /
lame string<\/pre>/, done)
-      })
+    it('should handle non-error-objects', function (done) {
+      request(createServer('lame string'))
+        .get('/foo')
+        .expect(500, /
lame string<\/pre>/, done)
+    })
 
-      it('should handle null prototype objects', function (done) {
-        request(createServer(Object.create(null)))
-          .get('/foo')
-          .expect(500, /
Internal Server Error<\/pre>/, done)
-      })
+    it('should handle null prototype objects', function (done) {
+      request(createServer(Object.create(null)))
+        .get('/foo')
+        .expect(500, /
Internal Server Error<\/pre>/, done)
+    })
 
-      it('should send staus code name when production', function (done) {
-        var err = createError('boom!', {
-          status: 501
-        })
-        request(createServer(err, {
-          env: 'production'
-        }))
-          .get('/foo')
-          .expect(501, /
Not Implemented<\/pre>/, done)
+    it('should send staus code name when production', function (done) {
+      var err = createError('boom!', {
+        status: 501
       })
+      request(createServer(err, {
+        env: 'production'
+      }))
+        .get('/foo')
+        .expect(501, /
Not Implemented<\/pre>/, done)
+    })
 
-      describe('when there is a request body', function () {
-        it('should not hang/error when unread', function (done) {
-          var buf = Buffer.alloc(1024 * 16, '.')
-          var server = createServer(new Error('boom!'))
-          var test = request(server).post('/foo')
-          test.write(buf)
-          test.write(buf)
-          test.write(buf)
-          test.expect(500, done)
-        })
-
-        it('should not hang/error when actively piped', function (done) {
-          var buf = Buffer.alloc(1024 * 16, '.')
-          var server = createServer(function (req, res, next) {
-            req.pipe(stream)
-            process.nextTick(function () {
-              next(new Error('boom!'))
-            })
-          })
-          var stream = createSlowWriteStream()
-          var test = request(server).post('/foo')
-          test.write(buf)
-          test.write(buf)
-          test.write(buf)
-          test.expect(500, done)
-        })
-
-        it('should not hang/error when read', function (done) {
-          var buf = Buffer.alloc(1024 * 16, '.')
-          var server = createServer(function (req, res, next) {
-            // read off the request
-            req.once('end', function () {
-              next(new Error('boom!'))
-            })
-            req.resume()
-          })
-          var test = request(server).post('/foo')
-          test.write(buf)
-          test.write(buf)
-          test.write(buf)
-          test.expect(500, done)
-        })
+    describe('when there is a request body', function () {
+      it('should not hang/error when unread', function (done) {
+        var buf = Buffer.alloc(1024 * 16, '.')
+        var server = createServer(new Error('boom!'))
+        var test = request(server).post('/foo')
+        test.write(buf)
+        test.write(buf)
+        test.write(buf)
+        test.expect(500, done)
       })
 
-      describe('when res.statusCode set', function () {
-        it('should keep when >= 400', function (done) {
-          var server = createServer(function (req, res) {
-            var done = finalhandler(req, res)
-            res.statusCode = 503
-            done(new Error('oops'))
-          })
-
-          request(server)
-            .get('/foo')
-            .expect(503, done)
-        })
-
-        it('should convert to 500 is not a number', function (done) {
-          var server = createServer(function (req, res) {
-            var done = finalhandler(req, res)
-            res.statusCode = 'oh no'
-            done(new Error('oops'))
-          })
-
-          request(server)
-            .get('/foo')
-            .expect(500, done)
-        })
-
-        it('should override with err.status', function (done) {
-          var server = createServer(function (req, res) {
-            var done = finalhandler(req, res)
-            var err = createError('oops', {
-              status: 414,
-              statusCode: 503
-            })
-            done(err)
-          })
-
-          request(server)
-            .get('/foo')
-            .expect(414, done)
-        })
-
-        it('should default body to status message in production', function (done) {
-          var err = createError('boom!', {
-            status: 509
+      it('should not hang/error when actively piped', function (done) {
+        var buf = Buffer.alloc(1024 * 16, '.')
+        var server = createServer(function (req, res, next) {
+          req.pipe(stream)
+          process.nextTick(function () {
+            next(new Error('boom!'))
           })
-          request(createServer(err, {
-            env: 'production'
-          }))
-            .get('/foo')
-            .expect(509, /
Bandwidth Limit Exceeded<\/pre>/, done)
         })
+        var stream = createSlowWriteStream()
+        var test = request(server).post('/foo')
+        test.write(buf)
+        test.write(buf)
+        test.write(buf)
+        test.expect(500, done)
       })
 
-      describe('when res.statusCode undefined', function () {
-        it('should set to 500', function (done) {
-          var server = createServer(function (req, res) {
-            var done = finalhandler(req, res)
-            res.statusCode = undefined
-            done(new Error('oops'))
+      it('should not hang/error when read', function (done) {
+        var buf = Buffer.alloc(1024 * 16, '.')
+        var server = createServer(function (req, res, next) {
+          // read off the request
+          req.once('end', function () {
+            next(new Error('boom!'))
           })
-
-          request(server)
-            .get('/foo')
-            .expect(500, done)
+          req.resume()
         })
+        var test = request(server).post('/foo')
+        test.write(buf)
+        test.write(buf)
+        test.write(buf)
+        test.expect(500, done)
       })
     })
 
-    describe('headers set', function () {
-      it('should persist set headers', function (done) {
+    describe('when res.statusCode set', function () {
+      it('should keep when >= 400', function (done) {
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.setHeader('Server', 'foobar')
-          done()
+          res.statusCode = 503
+          done(new Error('oops'))
         })
 
         request(server)
           .get('/foo')
-          .expect(404)
-          .expect('Server', 'foobar')
-          .end(done)
+          .expect(503, done)
       })
 
-      it('should override content-type and length', function (done) {
+      it('should convert to 500 is not a number', function (done) {
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.setHeader('Content-Type', 'image/png')
-          res.setHeader('Content-Length', '50')
-          done()
+          res.statusCode = 'oh no'
+          done(new Error('oops'))
         })
 
         request(server)
           .get('/foo')
-          .expect(404)
-          .expect('Content-Type', 'text/html; charset=utf-8')
-          .expect('Content-Length', '142')
-          .end(done)
+          .expect(500, done)
       })
 
-      it('should remove other content headers', function (done) {
+      it('should override with err.status', function (done) {
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.setHeader('Content-Encoding', 'gzip')
-          res.setHeader('Content-Language', 'jp')
-          res.setHeader('Content-Range', 'bytes 0-2/10')
-          done()
+          var err = createError('oops', {
+            status: 414,
+            statusCode: 503
+          })
+          done(err)
         })
 
         request(server)
           .get('/foo')
-          .expect(404)
-          .expect(shouldNotHaveHeader('Content-Encoding'))
-          .expect(shouldNotHaveHeader('Content-Language'))
-          .expect(shouldNotHaveHeader('Content-Range'))
-          .end(done)
+          .expect(414, done)
       })
-    })
 
-    describe('request started', function () {
-      it('should not respond', function (done) {
-        var server = createServer(function (req, res) {
-          var done = finalhandler(req, res)
-          res.statusCode = 301
-          res.write('0')
-          process.nextTick(function () {
-            done()
-            res.end('1')
-          })
+      it('should default body to status message in production', function (done) {
+        var err = createError('boom!', {
+          status: 509
         })
-
-        request(server)
+        request(createServer(err, {
+          env: 'production'
+        }))
           .get('/foo')
-          .expect(301, '01', done)
+          .expect(509, /
Bandwidth Limit Exceeded<\/pre>/, done)
       })
+    })
 
-      it('should terminate on error', function (done) {
+    describe('when res.statusCode undefined', function () {
+      it('should set to 500', function (done) {
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
-          res.statusCode = 301
-          res.write('0')
-          process.nextTick(function () {
-            done(createError('too many requests', {
-              status: 429,
-              headers: { 'Retry-After': '5' }
-            }))
-            res.end('1')
-          })
+          res.statusCode = undefined
+          done(new Error('oops'))
         })
 
         request(server)
           .get('/foo')
-          .on('request', function onrequest (test) {
-            test.req.on('response', function onresponse (res) {
-              if (res.listeners('error').length > 0) {
-                // forward aborts as errors for supertest
-                res.on('aborted', function onabort () {
-                  res.emit('error', new Error('aborted'))
-                })
-              }
-            })
-          })
-          .end(function (err) {
-            if (err && err.message !== 'aborted') return done(err)
-            assert.strictEqual(this.res.statusCode, 301)
-            assert.strictEqual(this.res.text, '0')
-            done()
-          })
+          .expect(500, done)
       })
     })
+  })
 
-    describe('onerror', function () {
-      it('should be invoked when error', function (done) {
-        var err = new Error('boom!')
-        var error
+  describe('headers set', function () {
+    it('should persist set headers', function (done) {
+      var server = createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        res.setHeader('Server', 'foobar')
+        done()
+      })
 
-        function log (e) {
-          error = e
-        }
+      request(server)
+        .get('/foo')
+        .expect(404)
+        .expect('Server', 'foobar')
+        .end(done)
+    })
 
-        request(createServer(err, { onerror: log }))
-          .get('/')
-          .end(function () {
-            assert.equal(error, err)
-            done()
-          })
+    it('should override content-type and length', function (done) {
+      var server = createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        res.setHeader('Content-Type', 'image/png')
+        res.setHeader('Content-Length', '50')
+        done()
       })
+
+      request(server)
+        .get('/foo')
+        .expect(404)
+        .expect('Content-Type', 'text/html; charset=utf-8')
+        .expect('Content-Length', '142')
+        .end(done)
     })
 
-    describe('no deprecation warnings', function () {
-      it('should respond 404 on no error', function (done) {
-        var http2
-        try {
-          http2 = require('http2')
-        } catch (e) {
-          return done()
-        }
+    it('should remove other content headers', function (done) {
+      var server = createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        res.setHeader('Content-Encoding', 'gzip')
+        res.setHeader('Content-Language', 'jp')
+        res.setHeader('Content-Range', 'bytes 0-2/10')
+        done()
+      })
+
+      request(server)
+        .get('/foo')
+        .expect(404)
+        .expect(shouldNotHaveHeader('Content-Encoding'))
+        .expect(shouldNotHaveHeader('Content-Language'))
+        .expect(shouldNotHaveHeader('Content-Range'))
+        .end(done)
+    })
+  })
+
+  describe('request started', function () {
+    it('should not respond', function (done) {
+      var server = createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        res.statusCode = 301
+        res.write('0')
+        process.nextTick(function () {
+          done()
+          res.end('1')
+        })
+      })
 
-        var warned = false
+      request(server)
+        .get('/foo')
+        .expect(301, '01', done)
+    })
 
-        process.once('warning', function (warning) {
-          if (/The http2 module is an experimental API/.test(warning)) return
-          assert.fail(warning)
+    it('should terminate on error', function (done) {
+      var server = createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        res.statusCode = 301
+        res.write('0')
+        process.nextTick(function () {
+          done(createError('too many requests', {
+            status: 429,
+            headers: { 'Retry-After': '5' }
+          }))
+          res.end('1')
         })
+      })
 
-        var server = http2.createServer(function (req, res) {
-          var done = finalhandler(req, res)
+      request(server)
+        .get('/foo')
+        .on('request', function onrequest (test) {
+          test.req.on('response', function onresponse (res) {
+            if (res.listeners('error').length > 0) {
+              // forward aborts as errors for supertest
+              res.on('aborted', function onabort () {
+                res.emit('error', new Error('aborted'))
+              })
+            }
+          })
+        })
+        .end(function (err) {
+          if (err && err.message !== 'aborted') return done(err)
+          assert.strictEqual(this.res.statusCode, 301)
+          assert.strictEqual(this.res.text, '0')
           done()
         })
+    })
+  })
 
-        server.listen(function () {
-          var port = server.address().port
-          var client = http2.connect('http://localhost:' + port)
-          var req = client.request({
-            ':method': 'GET',
-            ':path': '/foo'
-          })
+  describe('onerror', function () {
+    it('should be invoked when error', function (done) {
+      var err = new Error('boom!')
+      var error
 
-          req.on('response', function (headers) {
-            assert.strictEqual(headers[':status'], 404)
-            req.close()
-            client.close()
-            server.close()
-            assert.strictEqual(warned, false)
-            done()
-          })
+      function log (e) {
+        error = e
+      }
+
+      request(createServer(err, { onerror: log }))
+        .get('/')
+        .end(function () {
+          assert.equal(error, err)
+          done()
         })
+    })
+  })
+
+  describe('no deprecation warnings', function () {
+    it('should respond 404 on no error', function (done) {
+      var http2
+      try {
+        http2 = require('http2')
+      } catch (e) {
+        return done()
+      }
+
+      var warned = false
+
+      process.once('warning', function (warning) {
+        if (/The http2 module is an experimental API/.test(warning)) return
+        assert.fail(warning)
       })
 
-      it('should respond 500 on error', function (done) {
-        var http2
-        try {
-          http2 = require('http2')
-        } catch (e) {
-          return done()
-        }
+      var server = http2.createServer(function (req, res) {
+        var done = finalhandler(req, res)
+        done()
+      })
 
-        var warned = false
+      server.listen(function () {
+        var port = server.address().port
+        var client = http2.connect('http://localhost:' + port)
+        var req = client.request({
+          ':method': 'GET',
+          ':path': '/foo'
+        })
 
-        process.once('warning', function (warning) {
-          if (/The http2 module is an experimental API/.test(warning)) return
-          assert.fail(warning)
+        req.on('response', function (headers) {
+          assert.strictEqual(headers[':status'], 404)
+          req.close()
+          client.close()
+          server.close()
+          assert.strictEqual(warned, false)
+          done()
         })
+      })
+    })
 
-        var err = createError()
+    it('should respond 500 on error', function (done) {
+      var http2
+      try {
+        http2 = require('http2')
+      } catch (e) {
+        return done()
+      }
 
-        var server = http2.createServer(function (req, res) {
-          var done = finalhandler(req, res)
+      var warned = false
 
-          if (typeof err === 'function') {
-            err(req, res, done)
-            return
-          }
+      process.once('warning', function (warning) {
+        if (/The http2 module is an experimental API/.test(warning)) return
+        assert.fail(warning)
+      })
 
-          done(err)
-        })
+      var err = createError()
 
-        server.listen(function () {
-          var port = server.address().port
-          var client = http2.connect('http://localhost:' + port)
-          var req = client.request({
-            ':method': 'GET',
-            ':path': '/foo'
-          })
+      var server = http2.createServer(function (req, res) {
+        var done = finalhandler(req, res)
 
-          req.on('response', function (headers) {
-            assert.strictEqual(headers[':status'], 500)
-            req.close()
-            client.close()
-            server.close()
-            assert.strictEqual(warned, false)
-            done()
-          })
+        if (typeof err === 'function') {
+          err(req, res, done)
+          return
+        }
+
+        done(err)
+      })
+
+      server.listen(function () {
+        var port = server.address().port
+        var client = http2.connect('http://localhost:' + port)
+        var req = client.request({
+          ':method': 'GET',
+          ':path': '/foo'
+        })
+
+        req.on('response', function (headers) {
+          assert.strictEqual(headers[':status'], 500)
+          req.close()
+          client.close()
+          server.close()
+          assert.strictEqual(warned, false)
+          done()
         })
       })
     })
   })
 }
+
+var servers = [
+  ['http', createHTTPServer],
+  ['http2', createHTTP2Server]
+]
+
+for (var i = 0; i < servers.length; i++) {
+  var tests = topDescribe.bind(undefined, servers[i][1])
+
+  describe(servers[i][0], tests)
+}

From e2f9f7fafd0a2aabb9df83ada68c6739f69362fa Mon Sep 17 00:00:00 2001
From: "alexander.akait" 
Date: Wed, 21 Aug 2024 14:28:39 +0300
Subject: [PATCH 5/6] test: fix

---
 test/support/utils.js |  78 ++++++++++-
 test/test.js          | 294 +++++++++++++++++++++---------------------
 2 files changed, 222 insertions(+), 150 deletions(-)

diff --git a/test/support/utils.js b/test/support/utils.js
index 8734159..54bc490 100644
--- a/test/support/utils.js
+++ b/test/support/utils.js
@@ -1,6 +1,15 @@
 var assert = require('assert')
 var finalhandler = require('../..')
 var http = require('http')
+
+var http2
+
+try {
+  http2 = require('http2')
+} catch (_err) {
+  // Nothing
+}
+
 var request = require('supertest')
 var SlowWriteStream = require('./sws')
 
@@ -10,6 +19,7 @@ exports.createHTTPServer = createHTTPServer
 exports.createHTTP2Server = createHTTP2Server
 exports.createSlowWriteStream = createSlowWriteStream
 exports.rawrequest = rawrequest
+exports.rawrequestHTTP2 = rawrequestHTTP2
 exports.request = request
 exports.shouldHaveStatusMessage = shouldHaveStatusMessage
 exports.shouldNotHaveBody = shouldNotHaveBody
@@ -41,7 +51,7 @@ function createHTTPServer (err, opts) {
 }
 
 function createHTTP2Server (err, opts) {
-  return http.createServer(function (req, res) {
+  return http2.createServer(function (req, res) {
     var done = finalhandler(req, res, opts)
 
     if (typeof err === 'function') {
@@ -121,6 +131,72 @@ function rawrequest (server) {
   }
 }
 
+function rawrequestHTTP2 (server) {
+  var _headers = {}
+  var _path
+
+  function expect (status, body, callback) {
+    if (arguments.length === 2) {
+      _headers[status.toLowerCase()] = body
+      return this
+    }
+
+    server.listen(function onlisten () {
+      var buf = ''
+      var resHeaders
+      var addr = this.address()
+      var port = addr.port
+
+      var client = http2.connect('http://127.0.0.1:' + port)
+      var req = client.request({
+        ':method': 'GET',
+        ':path': _path.replace(/http:\/\/localhost/, '')
+      })
+      req.on('error', callback)
+      req.on('response', (responseHeaders) => {
+        resHeaders = responseHeaders
+      })
+      req.on('data', (s) => { buf += s })
+      req.on('end', () => {
+        var err = null
+
+        try {
+          for (var key in _headers) {
+            assert.strictEqual(resHeaders[key], _headers[key])
+          }
+
+          assert.strictEqual(resHeaders[':status'], status)
+
+          if (body instanceof RegExp) {
+            assert.ok(body.test(buf), 'expected body ' + buf + ' to match ' + body)
+          } else {
+            assert.strictEqual(buf, body, 'expected ' + body + ' response body, got ' + buf)
+          }
+        } catch (e) {
+          err = e
+        }
+
+        req.close()
+        client.close()
+        server.close()
+        callback(err)
+      })
+    })
+  }
+
+  function get (path) {
+    _path = path
+
+    return {
+      expect: expect
+    }
+  }
+
+  return {
+    get: get
+  }
+}
+
 function shouldHaveStatusMessage (statusMessage) {
   return function (test) {
     assert.strictEqual(test.res.statusMessage, statusMessage, 'should have statusMessage "' + statusMessage + '"')
diff --git a/test/test.js b/test/test.js
index a5e25dd..70091ff 100644
--- a/test/test.js
+++ b/test/test.js
@@ -2,6 +2,15 @@
 var Buffer = require('safe-buffer').Buffer
 var finalhandler = require('..')
 var http = require('http')
+
+var http2
+
+try {
+  http2 = require('http2')
+} catch (_err) {
+  // Nothing
+}
+
 var utils = require('./support/utils')
 
 var assert = utils.assert
@@ -10,173 +19,183 @@ var createHTTPServer = utils.createHTTPServer
 var createHTTP2Server = utils.createHTTP2Server
 var createSlowWriteStream = utils.createSlowWriteStream
 var rawrequest = utils.rawrequest
+var rawrequestHTTP2 = utils.rawrequestHTTP2
 var request = utils.request
 var shouldHaveStatusMessage = utils.shouldHaveStatusMessage
 var shouldNotHaveBody = utils.shouldNotHaveBody
 var shouldNotHaveHeader = utils.shouldNotHaveHeader
 
-var describeStatusMessage = !/statusMessage/.test(http.IncomingMessage.toString())
-  ? describe.skip
-  : describe
+var topDescribe = function (type, createServer) {
+  var wrapper = function wrapper (req) {
+    if (type === 'http2') {
+      return req.http2()
+    }
+
+    return req
+  }
 
-var topDescribe = function (createServer) {
   describe('headers', function () {
     it('should ignore err.headers without status code', function (done) {
-      request(createServer(createError('oops!', {
+      wrapper(request(createServer(createError('oops!', {
         headers: { 'X-Custom-Header': 'foo' }
       })))
-        .get('/')
+        .get('/'))
         .expect(shouldNotHaveHeader('X-Custom-Header'))
         .expect(500, done)
     })
 
     it('should ignore err.headers with invalid res.status', function (done) {
-      request(createServer(createError('oops!', {
+      wrapper(request(createServer(createError('oops!', {
         headers: { 'X-Custom-Header': 'foo' },
         status: 601
       })))
-        .get('/')
+        .get('/'))
         .expect(shouldNotHaveHeader('X-Custom-Header'))
         .expect(500, done)
     })
 
     it('should ignore err.headers with invalid res.statusCode', function (done) {
-      request(createServer(createError('oops!', {
+      wrapper(request(createServer(createError('oops!', {
         headers: { 'X-Custom-Header': 'foo' },
         statusCode: 601
       })))
-        .get('/')
+        .get('/'))
         .expect(shouldNotHaveHeader('X-Custom-Header'))
         .expect(500, done)
     })
 
     it('should include err.headers with err.status', function (done) {
-      request(createServer(createError('oops!', {
+      wrapper(request(createServer(createError('oops!', {
         headers: { 'X-Custom-Header': 'foo=500', 'X-Custom-Header2': 'bar' },
         status: 500
       })))
-        .get('/')
+        .get('/'))
         .expect('X-Custom-Header', 'foo=500')
         .expect('X-Custom-Header2', 'bar')
         .expect(500, done)
     })
 
     it('should include err.headers with err.statusCode', function (done) {
-      request(createServer(createError('too many requests', {
+      wrapper(request(createServer(createError('too many requests', {
         headers: { 'Retry-After': '5' },
         statusCode: 429
       })))
-        .get('/')
+        .get('/'))
         .expect('Retry-After', '5')
         .expect(429, done)
     })
 
     it('should ignore err.headers when not an object', function (done) {
-      request(createServer(createError('oops!', {
+      wrapper(request(createServer(createError('oops!', {
         headers: 'foobar',
         statusCode: 500
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
   })
 
   describe('status code', function () {
     it('should 404 on no error', function (done) {
-      request(createServer())
-        .get('/')
+      wrapper(request(createServer())
+        .get('/'))
         .expect(404, done)
     })
 
     it('should 500 on error', function (done) {
-      request(createServer(createError()))
-        .get('/')
+      wrapper(request(createServer(createError()))
+        .get('/'))
         .expect(500, done)
     })
 
     it('should use err.statusCode', function (done) {
-      request(createServer(createError('nope', {
+      wrapper(request(createServer(createError('nope', {
         statusCode: 400
       })))
-        .get('/')
+        .get('/'))
         .expect(400, done)
     })
 
     it('should ignore non-error err.statusCode code', function (done) {
-      request(createServer(createError('created', {
+      wrapper(request(createServer(createError('created', {
         statusCode: 201
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
 
     it('should ignore non-numeric err.statusCode', function (done) {
-      request(createServer(createError('oops', {
+      wrapper(request(createServer(createError('oops', {
         statusCode: 'oh no'
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
 
     it('should use err.status', function (done) {
-      request(createServer(createError('nope', {
+      wrapper(request(createServer(createError('nope', {
         status: 400
       })))
-        .get('/')
+        .get('/'))
         .expect(400, done)
     })
 
     it('should use err.status over err.statusCode', function (done) {
-      request(createServer(createError('nope', {
+      wrapper(request(createServer(createError('nope', {
         status: 400,
         statusCode: 401
       })))
-        .get('/')
+        .get('/'))
         .expect(400, done)
     })
 
     it('should set status to 500 when err.status < 400', function (done) {
-      request(createServer(createError('oops', {
+      wrapper(request(createServer(createError('oops', {
         status: 202
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
 
     it('should set status to 500 when err.status > 599', function (done) {
-      request(createServer(createError('oops', {
+      wrapper(request(createServer(createError('oops', {
         status: 601
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
 
     it('should use err.statusCode over invalid err.status', function (done) {
-      request(createServer(createError('nope', {
+      wrapper(request(createServer(createError('nope', {
         status: 50,
         statusCode: 410
       })))
-        .get('/')
+        .get('/'))
         .expect(410, done)
     })
 
     it('should ignore non-error err.status code', function (done) {
-      request(createServer(createError('created', {
+      wrapper(request(createServer(createError('created', {
         status: 201
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
 
     it('should ignore non-numeric err.status', function (done) {
-      request(createServer(createError('oops', {
+      wrapper(request(createServer(createError('oops', {
         status: 'oh no'
       })))
-        .get('/')
+        .get('/'))
         .expect(500, done)
     })
   })
 
+  // http2 does not support status message
+  var describeStatusMessage = !/statusMessage/.test(http.IncomingMessage.toString()) || type === 'http2'
+    ? describe.skip
+    : describe
+
   describeStatusMessage('status message', function () {
     it('should be "Not Found" on no error', function (done) {
       request(createServer())
@@ -216,13 +235,13 @@ var topDescribe = function (createServer) {
 
   describe('404 response', function () {
     it('should include method and pathname', function (done) {
-      request(createServer())
-        .get('/foo')
+      wrapper(request(createServer())
+        .get('/foo'))
         .expect(404, /
Cannot GET \/foo<\/pre>/, done)
     })
 
     it('should escape method and pathname characters', function (done) {
-      rawrequest(createServer())
+      (type === 'http2' ? rawrequestHTTP2 : rawrequest)(createServer())
         .get('/')
         .expect(404, /
Cannot GET \/%3Cla'me%3E<\/pre>/, done)
     })
@@ -233,8 +252,8 @@ var topDescribe = function (createServer) {
         next()
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .expect(404, /
Cannot GET resource<\/pre>/, done)
     })
 
@@ -246,35 +265,35 @@ var topDescribe = function (createServer) {
         next()
       })
 
-      request(server)
-        .get('/foo/bar')
+      wrapper(request(server)
+        .get('/foo/bar'))
         .expect(404, /
Cannot GET \/foo\/bar<\/pre>/, done)
     })
 
     it('should include pathname only', function (done) {
-      rawrequest(createServer())
+      (type === 'http2' ? rawrequestHTTP2 : rawrequest)(createServer())
         .get('http://localhost/foo?bar=1')
         .expect(404, /
Cannot GET \/foo<\/pre>/, done)
     })
 
     it('should handle HEAD', function (done) {
-      request(createServer())
-        .head('/foo')
+      wrapper(request(createServer())
+        .head('/foo'))
         .expect(404)
         .expect(shouldNotHaveBody())
         .end(done)
     })
 
     it('should include X-Content-Type-Options header', function (done) {
-      request(createServer())
-        .get('/foo')
+      wrapper(request(createServer())
+        .get('/foo'))
         .expect('X-Content-Type-Options', 'nosniff')
         .expect(404, done)
     })
 
     it('should include Content-Security-Policy header', function (done) {
-      request(createServer())
-        .get('/foo')
+      wrapper(request(createServer())
+        .get('/foo'))
         .expect('Content-Security-Policy', "default-src 'none'")
         .expect(404, done)
     })
@@ -282,7 +301,7 @@ var topDescribe = function (createServer) {
     it('should not hang/error if there is a request body', function (done) {
       var buf = Buffer.alloc(1024 * 16, '.')
       var server = createServer()
-      var test = request(server).post('/foo')
+      var test = wrapper(request(server).post('/foo'))
       test.write(buf)
       test.write(buf)
       test.write(buf)
@@ -292,42 +311,42 @@ var topDescribe = function (createServer) {
 
   describe('error response', function () {
     it('should include error stack', function (done) {
-      request(createServer(createError('boom!')))
-        .get('/foo')
+      wrapper(request(createServer(createError('boom!')))
+        .get('/foo'))
         .expect(500, /
Error: boom!
   at/, done) }) it('should handle HEAD', function (done) { - request(createServer(createError('boom!'))) - .head('/foo') + wrapper(request(createServer(createError('boom!'))) + .head('/foo')) .expect(500) .expect(shouldNotHaveBody()) .end(done) }) it('should include X-Content-Type-Options header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') + wrapper(request(createServer(createError('boom!'))) + .get('/foo')) .expect('X-Content-Type-Options', 'nosniff') .expect(500, done) }) it('should includeContent-Security-Policy header', function (done) { - request(createServer(createError('boom!'))) - .get('/foo') + wrapper(request(createServer(createError('boom!'))) + .get('/foo')) .expect('Content-Security-Policy', "default-src 'none'") .expect(500, done) }) it('should handle non-error-objects', function (done) { - request(createServer('lame string')) - .get('/foo') + wrapper(request(createServer('lame string')) + .get('/foo')) .expect(500, /
lame string<\/pre>/, done)
     })
 
     it('should handle null prototype objects', function (done) {
-      request(createServer(Object.create(null)))
-        .get('/foo')
+      wrapper(request(createServer(Object.create(null)))
+        .get('/foo'))
         .expect(500, /
Internal Server Error<\/pre>/, done)
     })
 
@@ -335,10 +354,10 @@ var topDescribe = function (createServer) {
       var err = createError('boom!', {
         status: 501
       })
-      request(createServer(err, {
+      wrapper(request(createServer(err, {
         env: 'production'
       }))
-        .get('/foo')
+        .get('/foo'))
         .expect(501, /
Not Implemented<\/pre>/, done)
     })
 
@@ -346,7 +365,7 @@ var topDescribe = function (createServer) {
       it('should not hang/error when unread', function (done) {
         var buf = Buffer.alloc(1024 * 16, '.')
         var server = createServer(new Error('boom!'))
-        var test = request(server).post('/foo')
+        var test = wrapper(request(server).post('/foo'))
         test.write(buf)
         test.write(buf)
         test.write(buf)
@@ -362,7 +381,7 @@ var topDescribe = function (createServer) {
           })
         })
         var stream = createSlowWriteStream()
-        var test = request(server).post('/foo')
+        var test = wrapper(request(server).post('/foo'))
         test.write(buf)
         test.write(buf)
         test.write(buf)
@@ -378,7 +397,7 @@ var topDescribe = function (createServer) {
           })
           req.resume()
         })
-        var test = request(server).post('/foo')
+        var test = wrapper(request(server).post('/foo'))
         test.write(buf)
         test.write(buf)
         test.write(buf)
@@ -394,20 +413,26 @@ var topDescribe = function (createServer) {
           done(new Error('oops'))
         })
 
-        request(server)
-          .get('/foo')
+        wrapper(request(server)
+          .get('/foo'))
           .expect(503, done)
       })
 
       it('should convert to 500 is not a number', function (done) {
+        // http2 does not support non numeric status code
+        if (type === 'http2') {
+          done()
+          return
+        }
+
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
           res.statusCode = 'oh no'
           done(new Error('oops'))
         })
 
-        request(server)
-          .get('/foo')
+        wrapper(request(server)
+          .get('/foo'))
           .expect(500, done)
       })
 
@@ -421,8 +446,8 @@ var topDescribe = function (createServer) {
           done(err)
         })
 
-        request(server)
-          .get('/foo')
+        wrapper(request(server)
+          .get('/foo'))
           .expect(414, done)
       })
 
@@ -430,24 +455,30 @@ var topDescribe = function (createServer) {
         var err = createError('boom!', {
           status: 509
         })
-        request(createServer(err, {
+        wrapper(request(createServer(err, {
           env: 'production'
         }))
-          .get('/foo')
+          .get('/foo'))
           .expect(509, /
Bandwidth Limit Exceeded<\/pre>/, done)
       })
     })
 
     describe('when res.statusCode undefined', function () {
       it('should set to 500', function (done) {
+        // http2 does not support non numeric status code
+        if (type === 'http2') {
+          done()
+          return
+        }
+
         var server = createServer(function (req, res) {
           var done = finalhandler(req, res)
           res.statusCode = undefined
           done(new Error('oops'))
         })
 
-        request(server)
-          .get('/foo')
+        wrapper(request(server)
+          .get('/foo'))
           .expect(500, done)
       })
     })
@@ -461,8 +492,8 @@ var topDescribe = function (createServer) {
         done()
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .expect(404)
         .expect('Server', 'foobar')
         .end(done)
@@ -476,8 +507,8 @@ var topDescribe = function (createServer) {
         done()
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .expect(404)
         .expect('Content-Type', 'text/html; charset=utf-8')
         .expect('Content-Length', '142')
@@ -493,8 +524,8 @@ var topDescribe = function (createServer) {
         done()
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .expect(404)
         .expect(shouldNotHaveHeader('Content-Encoding'))
         .expect(shouldNotHaveHeader('Content-Language'))
@@ -515,8 +546,8 @@ var topDescribe = function (createServer) {
         })
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .expect(301, '01', done)
     })
 
@@ -534,8 +565,8 @@ var topDescribe = function (createServer) {
         })
       })
 
-      request(server)
-        .get('/foo')
+      wrapper(request(server)
+        .get('/foo'))
         .on('request', function onrequest (test) {
           test.req.on('response', function onresponse (res) {
             if (res.listeners('error').length > 0) {
@@ -564,8 +595,8 @@ var topDescribe = function (createServer) {
         error = e
       }
 
-      request(createServer(err, { onerror: log }))
-        .get('/')
+      wrapper(request(createServer(err, { onerror: log }))
+        .get('/'))
         .end(function () {
           assert.equal(error, err)
           done()
@@ -575,13 +606,6 @@ var topDescribe = function (createServer) {
 
   describe('no deprecation warnings', function () {
     it('should respond 404 on no error', function (done) {
-      var http2
-      try {
-        http2 = require('http2')
-      } catch (e) {
-        return done()
-      }
-
       var warned = false
 
       process.once('warning', function (warning) {
@@ -589,38 +613,16 @@ var topDescribe = function (createServer) {
         assert.fail(warning)
       })
 
-      var server = http2.createServer(function (req, res) {
-        var done = finalhandler(req, res)
-        done()
-      })
-
-      server.listen(function () {
-        var port = server.address().port
-        var client = http2.connect('http://localhost:' + port)
-        var req = client.request({
-          ':method': 'GET',
-          ':path': '/foo'
-        })
-
-        req.on('response', function (headers) {
-          assert.strictEqual(headers[':status'], 404)
-          req.close()
-          client.close()
-          server.close()
+      wrapper(request(createServer())
+        .head('/foo'))
+        .expect(404)
+        .end(function (err) {
           assert.strictEqual(warned, false)
-          done()
+          done(err)
         })
-      })
     })
 
     it('should respond 500 on error', function (done) {
-      var http2
-      try {
-        http2 = require('http2')
-      } catch (e) {
-        return done()
-      }
-
       var warned = false
 
       process.once('warning', function (warning) {
@@ -630,7 +632,7 @@ var topDescribe = function (createServer) {
 
       var err = createError()
 
-      var server = http2.createServer(function (req, res) {
+      wrapper(request(createServer(function (req, res) {
         var done = finalhandler(req, res)
 
         if (typeof err === 'function') {
@@ -639,36 +641,30 @@ var topDescribe = function (createServer) {
         }
 
         done(err)
-      })
-
-      server.listen(function () {
-        var port = server.address().port
-        var client = http2.connect('http://localhost:' + port)
-        var req = client.request({
-          ':method': 'GET',
-          ':path': '/foo'
-        })
-
-        req.on('response', function (headers) {
-          assert.strictEqual(headers[':status'], 500)
-          req.close()
-          client.close()
-          server.close()
+      }))
+        .head('/foo'))
+        .expect(500)
+        .end(function (err, res) {
           assert.strictEqual(warned, false)
-          done()
+          done(err)
         })
-      })
     })
   })
 }
 
 var servers = [
-  ['http', createHTTPServer],
-  ['http2', createHTTP2Server]
+  ['http', createHTTPServer]
 ]
 
+var nodeVersion = process.versions.node.split('.').map(Number)
+
+// `superagent` only supports `http2` since Node.js@10
+if (http2 && nodeVersion[0] >= 10) {
+  servers.push(['http2', createHTTP2Server])
+}
+
 for (var i = 0; i < servers.length; i++) {
-  var tests = topDescribe.bind(undefined, servers[i][1])
+  var tests = topDescribe.bind(undefined, servers[i][0], servers[i][1])
 
   describe(servers[i][0], tests)
 }

From 8fcfd80bdfbeb616cafed87fdb3e7f61b5e17a24 Mon Sep 17 00:00:00 2001
From: "alexander.akait" 
Date: Wed, 21 Aug 2024 18:25:27 +0300
Subject: [PATCH 6/6] test: fix syntax

---
 test/support/utils.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/support/utils.js b/test/support/utils.js
index 54bc490..1ff3ff9 100644
--- a/test/support/utils.js
+++ b/test/support/utils.js
@@ -153,11 +153,11 @@ function rawrequestHTTP2 (server) {
         ':path': _path.replace(/http:\/\/localhost/, '')
       })
       req.on('error', callback)
-      req.on('response', (responseHeaders) => {
+      req.on('response', function onresponse (responseHeaders) {
         resHeaders = responseHeaders
       })
-      req.on('data', (s) => { buf += s })
-      req.on('end', () => {
+      req.on('data', function ondata (s) { buf += s })
+      req.on('end', function onend () {
         var err = null
 
         try {