4cd8b23032
Follow-up to the earlier enabling of classes/variables etc. Bug Related issues linked using fixes #number Integration tests added Errors have helpful link attached, see contributing.md Feature Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. Related issues linked using fixes #number Integration tests added Documentation added Telemetry added. In case of a feature if it's used or not. Errors have helpful link attached, see contributing.md Documentation / Examples Make sure the linting passes by running pnpm lint The examples guidelines are followed from our contributing doc Co-authored-by: Steven <steven@ceriously.com>
117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import type { NodeHeaders } from './types'
|
|
|
|
export function fromNodeHeaders(object: NodeHeaders): Headers {
|
|
const headers = new Headers()
|
|
for (let [key, value] of Object.entries(object)) {
|
|
const values = Array.isArray(value) ? value : [value]
|
|
for (let v of values) {
|
|
if (v !== undefined) {
|
|
headers.append(key, v)
|
|
}
|
|
}
|
|
}
|
|
return headers
|
|
}
|
|
|
|
/*
|
|
Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
|
|
that are within a single set-cookie field-value, such as in the Expires portion.
|
|
This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
|
|
Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
|
|
React Native's fetch does this for *every* header, including set-cookie.
|
|
|
|
Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
|
|
Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
|
|
*/
|
|
export function splitCookiesString(cookiesString: string) {
|
|
var cookiesStrings = []
|
|
var pos = 0
|
|
var start
|
|
var ch
|
|
var lastComma
|
|
var nextStart
|
|
var cookiesSeparatorFound
|
|
|
|
function skipWhitespace() {
|
|
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
|
pos += 1
|
|
}
|
|
return pos < cookiesString.length
|
|
}
|
|
|
|
function notSpecialChar() {
|
|
ch = cookiesString.charAt(pos)
|
|
|
|
return ch !== '=' && ch !== ';' && ch !== ','
|
|
}
|
|
|
|
while (pos < cookiesString.length) {
|
|
start = pos
|
|
cookiesSeparatorFound = false
|
|
|
|
while (skipWhitespace()) {
|
|
ch = cookiesString.charAt(pos)
|
|
if (ch === ',') {
|
|
// ',' is a cookie separator if we have later first '=', not ';' or ','
|
|
lastComma = pos
|
|
pos += 1
|
|
|
|
skipWhitespace()
|
|
nextStart = pos
|
|
|
|
while (pos < cookiesString.length && notSpecialChar()) {
|
|
pos += 1
|
|
}
|
|
|
|
// currently special character
|
|
if (pos < cookiesString.length && cookiesString.charAt(pos) === '=') {
|
|
// we found cookies separator
|
|
cookiesSeparatorFound = true
|
|
// pos is inside the next cookie, so back up and return it.
|
|
pos = nextStart
|
|
cookiesStrings.push(cookiesString.substring(start, lastComma))
|
|
start = pos
|
|
} else {
|
|
// in param ',' or param separator ';',
|
|
// we continue from that comma
|
|
pos = lastComma + 1
|
|
}
|
|
} else {
|
|
pos += 1
|
|
}
|
|
}
|
|
|
|
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
|
cookiesStrings.push(cookiesString.substring(start, cookiesString.length))
|
|
}
|
|
}
|
|
|
|
return cookiesStrings
|
|
}
|
|
|
|
export function toNodeHeaders(headers?: Headers): NodeHeaders {
|
|
const result: NodeHeaders = {}
|
|
if (headers) {
|
|
for (const [key, value] of headers.entries()) {
|
|
result[key] = value
|
|
if (key.toLowerCase() === 'set-cookie') {
|
|
result[key] = splitCookiesString(value)
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Validate the correctness of a user-provided URL.
|
|
*/
|
|
export function validateURL(url: string | URL): string {
|
|
try {
|
|
return String(new URL(String(url)))
|
|
} catch (error: any) {
|
|
throw new Error(
|
|
`URLs is malformed. Please use only absolute URLs - https://nextjs.org/docs/messages/middleware-relative-urls`,
|
|
{ cause: error }
|
|
)
|
|
}
|
|
}
|