Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename header conversion functions #50389

Merged
merged 3 commits into from May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/next/src/export/worker.ts
Expand Up @@ -43,7 +43,7 @@ import { NEXT_DYNAMIC_NO_SSR_CODE } from '../shared/lib/lazy-dynamic/no-ssr-erro
import { createRequestResponseMocks } from '../server/lib/mock-request'
import { NodeNextRequest } from '../server/base-http/node'
import { isAppRouteRoute } from '../lib/is-app-route-route'
import { toNodeHeaders } from '../server/web/utils'
import { toNodeOutgoingHttpHeaders } from '../server/web/utils'
import { RouteModuleLoader } from '../server/future/helpers/module-loader/route-module-loader'
import { NextRequestAdapter } from '../server/web/spec-extension/adapters/next-request'
import * as ciEnvironment from '../telemetry/ci-info'
Expand Down Expand Up @@ -445,7 +445,7 @@ export default async function exportPage({
context.staticGenerationContext.store?.revalidate || false

results.fromBuildExportRevalidate = revalidate
const headers = toNodeHeaders(response.headers)
const headers = toNodeOutgoingHttpHeaders(response.headers)
const cacheTags = (context.staticGenerationContext as any)
.fetchTags

Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/base-http/web.ts
@@ -1,5 +1,5 @@
import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http'
import { toNodeHeaders } from '../web/utils'
import { toNodeOutgoingHttpHeaders } from '../web/utils'

import { BaseNextRequest, BaseNextResponse } from './index'

Expand Down Expand Up @@ -81,7 +81,7 @@ export class WebNextResponse extends BaseNextResponse<WritableStream> {
}

getHeaders(): OutgoingHttpHeaders {
return toNodeHeaders(this.headers)
return toNodeOutgoingHttpHeaders(this.headers)
}

hasHeader(name: string): boolean {
Expand Down
9 changes: 6 additions & 3 deletions packages/next/src/server/base-server.ts
Expand Up @@ -100,7 +100,10 @@ import { I18NProvider } from './future/helpers/i18n-provider'
import { sendResponse } from './send-response'
import { RouteKind } from './future/route-kind'
import { handleInternalServerErrorResponse } from './future/route-modules/helpers/response-handlers'
import { fromNodeHeaders, toNodeHeaders } from './web/utils'
import {
fromNodeOutgoingHttpHeaders,
toNodeOutgoingHttpHeaders,
} from './web/utils'
import { NEXT_QUERY_PARAM_PREFIX } from '../lib/constants'

export type FindComponentsResult = {
Expand Down Expand Up @@ -1626,7 +1629,7 @@ export default abstract class Server<ServerOptions extends Options = Options> {
const blob = await response.blob()

// Copy the headers from the response.
const headers = toNodeHeaders(response.headers)
const headers = toNodeOutgoingHttpHeaders(response.headers)

if (cacheTags) {
headers['x-next-cache-tags'] = cacheTags
Expand Down Expand Up @@ -2024,7 +2027,7 @@ export default abstract class Server<ServerOptions extends Options = Options> {
req,
res,
new Response(cachedData.body, {
headers: fromNodeHeaders(headers),
headers: fromNodeOutgoingHttpHeaders(headers),
status: cachedData.status || 200,
})
)
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/lib/mock-request.ts
Expand Up @@ -9,7 +9,7 @@ import type { Socket } from 'net'
import type { TLSSocket } from 'tls'

import Stream from 'stream'
import { toNodeHeaders } from '../web/utils'
import { toNodeOutgoingHttpHeaders } from '../web/utils'

interface MockedRequestOptions {
url: string
Expand Down Expand Up @@ -240,7 +240,7 @@ export class MockedResponse extends Stream.Writable implements ServerResponse {
}

public getHeaders(): OutgoingHttpHeaders {
return toNodeHeaders(this.headers)
return toNodeOutgoingHttpHeaders(this.headers)
}

public getHeaderNames(): string[] {
Expand Down
6 changes: 3 additions & 3 deletions packages/next/src/server/next-server.ts
Expand Up @@ -78,7 +78,7 @@ import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
import { loadComponents } from './load-components'
import isError, { getProperError } from '../lib/is-error'
import { FontManifest } from './font-utils'
import { splitCookiesString, toNodeHeaders } from './web/utils'
import { splitCookiesString, toNodeOutgoingHttpHeaders } from './web/utils'
import { relativizeURL } from '../shared/lib/router/utils/relativize-url'
import { prepareDestination } from '../shared/lib/router/utils/prepare-destination'
import { getMiddlewareRouteMatcher } from '../shared/lib/router/utils/middleware-route-matcher'
Expand Down Expand Up @@ -2496,7 +2496,7 @@ export default class NextNodeServer extends BaseServer {

if (isMiddlewareInvoke && 'response' in result) {
for (const [key, value] of Object.entries(
toNodeHeaders(result.response.headers)
toNodeOutgoingHttpHeaders(result.response.headers)
)) {
if (key !== 'content-encoding' && value !== undefined) {
res.setHeader(key, value as string | string[])
Expand Down Expand Up @@ -2590,7 +2590,7 @@ export default class NextNodeServer extends BaseServer {
result.response.headers.delete('x-middleware-next')

for (const [key, value] of Object.entries(
toNodeHeaders(result.response.headers)
toNodeOutgoingHttpHeaders(result.response.headers)
)) {
if (
[
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/web/adapter.ts
@@ -1,7 +1,7 @@
import type { NextMiddleware, RequestData, FetchEventResult } from './types'
import type { RequestInit } from './spec-extension/request'
import { PageSignatureError } from './error'
import { fromNodeHeaders } from './utils'
import { fromNodeOutgoingHttpHeaders } from './utils'
import { NextFetchEvent } from './spec-extension/fetch-event'
import { NextRequest } from './spec-extension/request'
import { NextResponse } from './spec-extension/response'
Expand Down Expand Up @@ -127,7 +127,7 @@ export async function adapter(
requestUrl.pathname = '/'
}

const requestHeaders = fromNodeHeaders(params.request.headers)
const requestHeaders = fromNodeOutgoingHttpHeaders(params.request.headers)
const flightHeaders = new Map()
// Parameters should only be stripped for middleware
if (!isEdgeRendering) {
Expand Down
Expand Up @@ -3,7 +3,7 @@ import type { NodeNextRequest } from '../../../base-http/node'
import type { WebNextRequest } from '../../../base-http/web'

import { getRequestMeta } from '../../../request-meta'
import { fromNodeHeaders } from '../../utils'
import { fromNodeOutgoingHttpHeaders } from '../../utils'
import { NextRequest } from '../request'

export class NextRequestAdapter {
Expand Down Expand Up @@ -38,7 +38,7 @@ export class NextRequestAdapter {
return new NextRequest(url, {
body,
method: request.method,
headers: fromNodeHeaders(request.headers),
headers: fromNodeOutgoingHttpHeaders(request.headers),
// @ts-expect-error - see https://github.com/whatwg/fetch/pull/1457
duplex: 'half',
// geo
Expand All @@ -57,7 +57,7 @@ export class NextRequestAdapter {
return new NextRequest(request.url, {
body,
method: request.method,
headers: fromNodeHeaders(request.headers),
headers: fromNodeOutgoingHttpHeaders(request.headers),
// @ts-expect-error - see https://github.com/whatwg/fetch/pull/1457
duplex: 'half',
// geo
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/web/spec-extension/request.ts
@@ -1,7 +1,7 @@
import type { I18NConfig } from '../../config-shared'
import type { RequestData } from '../types'
import { NextURL } from '../next-url'
import { toNodeHeaders, validateURL } from '../utils'
import { toNodeOutgoingHttpHeaders, validateURL } from '../utils'
import { RemovedUAError, RemovedPageError } from '../error'
import { RequestCookies } from './cookies'

Expand All @@ -22,7 +22,7 @@ export class NextRequest extends Request {
validateURL(url)
super(url, init)
const nextUrl = new NextURL(url, {
headers: toNodeHeaders(this.headers),
headers: toNodeOutgoingHttpHeaders(this.headers),
nextConfig: init.nextConfig,
})
this[INTERNALS] = {
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/web/spec-extension/response.ts
@@ -1,6 +1,6 @@
import type { I18NConfig } from '../../config-shared'
import { NextURL } from '../next-url'
import { toNodeHeaders, validateURL } from '../utils'
import { toNodeOutgoingHttpHeaders, validateURL } from '../utils'

import { ResponseCookies } from './cookies'

Expand Down Expand Up @@ -40,7 +40,7 @@ export class NextResponse<Body = unknown> extends Response {
cookies: new ResponseCookies(this.headers),
url: init.url
? new NextURL(init.url, {
headers: toNodeHeaders(this.headers),
headers: toNodeOutgoingHttpHeaders(this.headers),
nextConfig: init.nextConfig,
})
: undefined,
Expand Down
16 changes: 6 additions & 10 deletions packages/next/src/server/web/utils.test.ts
@@ -1,4 +1,4 @@
import { toNodeHeaders } from './utils'
import { toNodeOutgoingHttpHeaders } from './utils'

// We use `Headers` here which is provided by the polyfill.
import '../node-polyfill-fetch'
Expand All @@ -10,7 +10,7 @@ describe('toNodeHeaders', () => {
headers.append('set-cookie', 'foo=bar')
headers.append('set-cookie', 'bar=foo')

expect(toNodeHeaders(headers)).toEqual({
expect(toNodeOutgoingHttpHeaders(headers)).toEqual({
'set-cookie': ['foo=bar', 'bar=foo'],
})
})
Expand All @@ -20,7 +20,7 @@ describe('toNodeHeaders', () => {

headers.append('set-cookie', 'foo=bar')

expect(toNodeHeaders(headers)).toEqual({
expect(toNodeOutgoingHttpHeaders(headers)).toEqual({
'set-cookie': 'foo=bar',
})
})
Expand All @@ -30,13 +30,13 @@ describe('toNodeHeaders', () => {

headers.append('set-cookie', 'foo=bar, bar=foo')

expect(toNodeHeaders(headers)).toEqual({
expect(toNodeOutgoingHttpHeaders(headers)).toEqual({
'set-cookie': ['foo=bar', 'bar=foo'],
})

headers.append('set-cookie', 'baz=qux')

expect(toNodeHeaders(headers)).toEqual({
expect(toNodeOutgoingHttpHeaders(headers)).toEqual({
'set-cookie': ['foo=bar', 'bar=foo', 'baz=qux'],
})
})
Expand All @@ -47,12 +47,8 @@ describe('toNodeHeaders', () => {
headers.append('set-cookie', 'foo=bar')
headers.append('Set-Cookie', 'bar=foo')

expect(toNodeHeaders(headers)).toEqual({
expect(toNodeOutgoingHttpHeaders(headers)).toEqual({
'set-cookie': ['foo=bar', 'bar=foo'],
})
})

it('should return an empty object when no headers are provided', () => {
expect(toNodeHeaders()).toEqual({})
})
})
34 changes: 27 additions & 7 deletions packages/next/src/server/web/utils.ts
@@ -1,8 +1,19 @@
import type { OutgoingHttpHeaders } from 'http'

export function fromNodeHeaders(object: OutgoingHttpHeaders): Headers {
/**
* Converts a Node.js IncomingHttpHeaders object to a Headers object. Any
* headers with multiple values will be joined with a comma and space. Any
* headers that have an undefined value will be ignored and others will be
* coerced to strings.
*
* @param nodeHeaders the headers object to convert
* @returns the converted headers object
*/
export function fromNodeOutgoingHttpHeaders(
nodeHeaders: OutgoingHttpHeaders
): Headers {
const headers = new Headers()
for (let [key, value] of Object.entries(object)) {
for (let [key, value] of Object.entries(nodeHeaders)) {
const values = Array.isArray(value) ? value : [value]
for (let v of values) {
if (typeof v === 'undefined') continue
Expand Down Expand Up @@ -92,8 +103,17 @@ export function splitCookiesString(cookiesString: string) {
return cookiesStrings
}

export function toNodeHeaders(headers?: Headers): OutgoingHttpHeaders {
const result: OutgoingHttpHeaders = {}
/**
* Converts a Headers object to a Node.js OutgoingHttpHeaders object. This is
* required to support the set-cookie header, which may have multiple values.
*
* @param headers the headers object to convert
* @returns the converted headers object
*/
export function toNodeOutgoingHttpHeaders(
headers: Headers
): OutgoingHttpHeaders {
const nodeHeaders: OutgoingHttpHeaders = {}
const cookies: string[] = []
if (headers) {
for (const [key, value] of headers.entries()) {
Expand All @@ -102,13 +122,13 @@ export function toNodeHeaders(headers?: Headers): OutgoingHttpHeaders {
// set-cookie headers. We need to merge them into one header array
// to represent all the cookies.
cookies.push(...splitCookiesString(value))
result[key] = cookies.length === 1 ? cookies[0] : cookies
nodeHeaders[key] = cookies.length === 1 ? cookies[0] : cookies
} else {
result[key] = value
nodeHeaders[key] = value
}
}
}
return result
return nodeHeaders
}

/**
Expand Down