From cfb661d0f0513acd643925d5e942d2869cbb9765 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 17 Oct 2022 21:16:23 +0100 Subject: [PATCH 1/7] fix: handle object-format early hints --- src/utils/response.ts | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index a7d1d88b..434d15b7 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -1,4 +1,4 @@ -import type { OutgoingMessage } from 'http' +import type { OutgoingMessage, ServerResponse } from 'http' import { createError } from '../error' import type { H3Event } from '../event' import { MIMES } from './consts' @@ -86,7 +86,7 @@ export function sendStream (event: H3Event, data: any): Promise { }) } -export function writeEarlyHints (event: H3Event, links: string | string[], callback?: () => void) { +export function writeEarlyHints (event: H3Event, hints: Record, callback?: () => void) { if (!event.res.socket && !('writeEarlyHints' in event.res)) { if (callback) { callback() @@ -94,11 +94,35 @@ export function writeEarlyHints (event: H3Event, links: string | string[], callb return } + // Normalize if string is provided + if (typeof hints === 'string') { + hints = { link: hints } + } + if ('writeEarlyHints' in event.res) { - // @ts-expect-error native node 18 implementation - return event.res.writeEarlyHints(links, callback) + return event.res.writeEarlyHints(hints, callback) } - const _links = Array.isArray(links) ? links : [links] - event.res.socket!.write(`HTTP/1.1 103 Early Hints\r\nLink: ${_links.join('\r\n')}\r\n\r\n`, 'utf-8', callback) + const headers: [string, string | string[]][] = Object.entries(hints) + if (!headers.length) { + if (callback) { + callback() + } + return + } + + let hint = 'HTTP/1.1 103 Early Hints' + const [, link] = headers.find(([header]) => header.toLowerCase() === 'link') || [] + if (link) { + const links = Array.isArray(link) ? link : [link] + hint += `\r\nLink: ${links.join('\r\n') + // TODO: remove when https://github.com/nodejs/node/pull/44874 is released + .replace(/; crossorigin/g, '').split(', ')}` + } + + for (const [header, value] of headers) { + if (header.toLowerCase() === 'link') { continue } + hint += `\r\n${header}: ${value}` + } + (event.res as ServerResponse).socket!.write(`${hint}\r\n\r\n`, 'utf-8', callback) } From 23957c2e6f468eb710f120901d16f3e76175cb88 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 17 Oct 2022 22:38:21 +0200 Subject: [PATCH 2/7] small refactors --- src/utils/response.ts | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index 434d15b7..afbb0328 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -86,35 +86,31 @@ export function sendStream (event: H3Event, data: any): Promise { }) } -export function writeEarlyHints (event: H3Event, hints: Record, callback?: () => void) { +const noop = () => {} +export function writeEarlyHints (event: H3Event, hints: string | string[] | Record, cb: () => void = noop) { if (!event.res.socket && !('writeEarlyHints' in event.res)) { - if (callback) { - callback() - } + cb() return } - // Normalize if string is provided - if (typeof hints === 'string') { + // Normalize if string or string[] is provided + if (typeof hints === 'string' || Array.isArray(hints)) { hints = { link: hints } } if ('writeEarlyHints' in event.res) { - return event.res.writeEarlyHints(hints, callback) + return event.res.writeEarlyHints(hints, cb) } const headers: [string, string | string[]][] = Object.entries(hints) if (!headers.length) { - if (callback) { - callback() - } + cb() return } let hint = 'HTTP/1.1 103 Early Hints' - const [, link] = headers.find(([header]) => header.toLowerCase() === 'link') || [] - if (link) { - const links = Array.isArray(link) ? link : [link] + if (hints.link) { + const links = Array.isArray(hints.link) ? hints.link : Array.from(hints.link) hint += `\r\nLink: ${links.join('\r\n') // TODO: remove when https://github.com/nodejs/node/pull/44874 is released .replace(/; crossorigin/g, '').split(', ')}` @@ -124,5 +120,5 @@ export function writeEarlyHints (event: H3Event, hints: Record Date: Mon, 17 Oct 2022 22:42:58 +0200 Subject: [PATCH 3/7] fix make all header keys lowercase --- src/utils/response.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index afbb0328..78e1bfb7 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -102,7 +102,7 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco return event.res.writeEarlyHints(hints, cb) } - const headers: [string, string | string[]][] = Object.entries(hints) + const headers: [string, string | string[]][] = Object.entries(hints).map(e => [e[0].toLowerCase(), e[1]]) if (!headers.length) { cb() return @@ -117,7 +117,7 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco } for (const [header, value] of headers) { - if (header.toLowerCase() === 'link') { continue } + if (header === 'link') { continue } hint += `\r\n${header}: ${value}` } (event.res as ServerResponse).socket!.write(`${hint}\r\n\r\n`, 'utf-8', cb) From 02d33e3c6a6091cf93ec87c33051aaef9866d6eb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 17 Oct 2022 22:49:35 +0200 Subject: [PATCH 4/7] fix typo --- src/utils/response.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index 78e1bfb7..54fd5949 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -110,7 +110,7 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco let hint = 'HTTP/1.1 103 Early Hints' if (hints.link) { - const links = Array.isArray(hints.link) ? hints.link : Array.from(hints.link) + const links = Array.isArray(hints.link) ? hints.link : [hints.link] hint += `\r\nLink: ${links.join('\r\n') // TODO: remove when https://github.com/nodejs/node/pull/44874 is released .replace(/; crossorigin/g, '').split(', ')}` From dfccdf4acd65347ac4320bdf0cc9a0b45b731a6f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 17 Oct 2022 21:48:33 +0100 Subject: [PATCH 5/7] fix: normalize links earlier --- src/utils/response.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index 54fd5949..1f573ba6 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -97,6 +97,9 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco if (typeof hints === 'string' || Array.isArray(hints)) { hints = { link: hints } } + hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(', ') + // TODO: remove when https://github.com/nodejs/node/pull/44874 is released + hints.link = hints.link.map(l => l.replace(/; crossorigin/g, '')) if ('writeEarlyHints' in event.res) { return event.res.writeEarlyHints(hints, cb) @@ -110,10 +113,7 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco let hint = 'HTTP/1.1 103 Early Hints' if (hints.link) { - const links = Array.isArray(hints.link) ? hints.link : [hints.link] - hint += `\r\nLink: ${links.join('\r\n') - // TODO: remove when https://github.com/nodejs/node/pull/44874 is released - .replace(/; crossorigin/g, '').split(', ')}` + hint += `\r\nLink: ${hints.link.join('\r\n')}` } for (const [header, value] of headers) { From d8f5d7dd4869db9e4b78b5bc2dd27e7ab13ac0ae Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 17 Oct 2022 22:53:47 +0200 Subject: [PATCH 6/7] add headers.link guard before normalizing --- src/utils/response.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index 1f573ba6..ea6baa91 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -97,9 +97,12 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco if (typeof hints === 'string' || Array.isArray(hints)) { hints = { link: hints } } - hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(', ') - // TODO: remove when https://github.com/nodejs/node/pull/44874 is released - hints.link = hints.link.map(l => l.replace(/; crossorigin/g, '')) + + if (hints.link) { + hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(', ') + // TODO: remove when https://github.com/nodejs/node/pull/44874 is released + hints.link = hints.link.map(l => l.replace(/; crossorigin/g, '')) + } if ('writeEarlyHints' in event.res) { return event.res.writeEarlyHints(hints, cb) @@ -113,7 +116,7 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco let hint = 'HTTP/1.1 103 Early Hints' if (hints.link) { - hint += `\r\nLink: ${hints.link.join('\r\n')}` + hint += `\r\nLink: ${(hints.link as string[]).join('\r\n')}` } for (const [header, value] of headers) { From d732e7c9b7a1c8feca88c7b5f7f2c211657406d0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 17 Oct 2022 22:55:21 +0200 Subject: [PATCH 7/7] split by comma and trim --- src/utils/response.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index ea6baa91..c0771e90 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -99,9 +99,9 @@ export function writeEarlyHints (event: H3Event, hints: string | string[] | Reco } if (hints.link) { - hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(', ') + hints.link = Array.isArray(hints.link) ? hints.link : hints.link.split(',') // TODO: remove when https://github.com/nodejs/node/pull/44874 is released - hints.link = hints.link.map(l => l.replace(/; crossorigin/g, '')) + hints.link = hints.link.map(l => l.trim().replace(/; crossorigin/g, '')) } if ('writeEarlyHints' in event.res) {