diff --git a/src/listener.ts b/src/listener.ts index 0e637cd..6022240 100644 --- a/src/listener.ts +++ b/src/listener.ts @@ -150,6 +150,7 @@ const responseViaResponseObject = async ( export const getRequestListener = ( fetchCallback: FetchCallback, options: { + hostname?: string errorHandler?: CustomErrorHandler overrideGlobalObjects?: boolean } = {} @@ -173,7 +174,7 @@ export const getRequestListener = ( try { // `fetchCallback()` requests a Request object, but global.Request is expensive to generate, // so generate a pseudo Request object with only the minimum required information. - req = newRequest(incoming) + req = newRequest(incoming, options.hostname) // Detect if request was aborted. outgoing.on('close', () => { diff --git a/src/request.ts b/src/request.ts index a8b7f65..3ec8116 100644 --- a/src/request.ts +++ b/src/request.ts @@ -130,11 +130,16 @@ const requestPrototype: Record = { }) Object.setPrototypeOf(requestPrototype, Request.prototype) -export const newRequest = (incoming: IncomingMessage | Http2ServerRequest) => { +export const newRequest = ( + incoming: IncomingMessage | Http2ServerRequest, + defaultHostname?: string +) => { const req = Object.create(requestPrototype) req[incomingKey] = incoming - const host = incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host + const host = + (incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host) || + defaultHostname if (!host) { throw new RequestError('Missing host header') } diff --git a/src/server.ts b/src/server.ts index d1b3146..c02fcc8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -6,6 +6,7 @@ import type { Options, ServerType } from './types' export const createAdaptorServer = (options: Options): ServerType => { const fetchCallback = options.fetch const requestListener = getRequestListener(fetchCallback, { + hostname: options.hostname, overrideGlobalObjects: options.overrideGlobalObjects, }) // ts will complain about createServerHTTP and createServerHTTP2 not being callable, which works just fine diff --git a/test/listener.test.ts b/test/listener.test.ts index a1e6eeb..bf1527b 100644 --- a/test/listener.test.ts +++ b/test/listener.test.ts @@ -1,28 +1,69 @@ import { createServer } from 'node:http' import request from 'supertest' import { getRequestListener } from '../src/listener' -import { GlobalRequest, Request as LightweightRequest } from '../src/request' +import { GlobalRequest, Request as LightweightRequest, RequestError } from '../src/request' import { GlobalResponse, Response as LightweightResponse } from '../src/response' describe('Invalid request', () => { - const requestListener = getRequestListener(jest.fn()) - const server = createServer(async (req, res) => { - await requestListener(req, res) + describe('default error handler', () => { + const requestListener = getRequestListener(jest.fn()) + const server = createServer(requestListener) - if (!res.writableEnded) { - res.writeHead(500, { 'Content-Type': 'text/plain' }) - res.end('error handler did not return a response') - } + it('Should return server error for a request w/o host header', async () => { + const res = await request(server).get('/').set('Host', '').send() + expect(res.status).toBe(400) + }) + + it('Should return server error for a request invalid host header', async () => { + const res = await request(server).get('/').set('Host', 'a b').send() + expect(res.status).toBe(400) + }) }) - it('Should return server error for a request w/o host header', async () => { - const res = await request(server).get('/').set('Host', '').send() - expect(res.status).toBe(400) + describe('custom error handler', () => { + const requestListener = getRequestListener(jest.fn(), { + errorHandler: (e) => { + if (e instanceof RequestError) { + return new Response(e.message, { status: 400 }) + } + else { + return new Response('unknown error', { status: 500 }) + } + }, + }) + const server = createServer(requestListener) + + it('Should return server error for a request w/o host header', async () => { + const res = await request(server).get('/').set('Host', '').send() + expect(res.status).toBe(400) + }) + + it('Should return server error for a request invalid host header', async () => { + const res = await request(server).get('/').set('Host', 'a b').send() + expect(res.status).toBe(400) + }) + + it('Should return server error for host header with path', async () => { + const res = await request(server).get('/').set('Host', 'a/b').send() + expect(res.status).toBe(400) + }) }) - it('Should return server error for a request invalid host header', async () => { - const res = await request(server).get('/').set('Host', 'a b').send() - expect(res.status).toBe(400) + describe('default hostname', () => { + const requestListener = getRequestListener(() => new Response('ok'), { + hostname: 'example.com', + }) + const server = createServer(requestListener) + + it('Should return 200 for a request w/o host header', async () => { + const res = await request(server).get('/').set('Host', '').send() + expect(res.status).toBe(200) + }) + + it('Should return server error for a request invalid host header', async () => { + const res = await request(server).get('/').set('Host', 'a b').send() + expect(res.status).toBe(400) + }) }) })