Skip to content

Commit

Permalink
Fix types, pull in middleware header fix from next.js
Browse files Browse the repository at this point in the history
Next js PR w/ the header fix:
vercel/next.js#30560
  • Loading branch information
gdborton committed Oct 29, 2021
1 parent c0be550 commit a38b0bc
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/middleware/src/websandbox/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NextFetchEvent } from './spec-extension/fetch-event';
import { NextRequest, RequestInit } from './spec-extension/request';
import { SpecResponse } from './spec-extension/response';
import { waitUntilSymbol } from './spec-compliant/fetch-event';
import { Response } from 'node-fetch';

export async function adapter(params: {
handler: (request: NextRequest, event: NextFetchEvent) => Promise<Response>;
Expand Down
2 changes: 2 additions & 0 deletions packages/middleware/src/websandbox/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Response } from 'node-fetch';

export interface NodeHeaders {
[header: string]: string | string[] | undefined;
}
Expand Down
78 changes: 77 additions & 1 deletion packages/middleware/src/websandbox/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,85 @@ export function toNodeHeaders(headers?: Headers): NodeHeaders {
for (const [key, value] of headers.entries()) {
result[key] = value;
if (key.toLowerCase() === 'set-cookie') {
result[key] = value.split(', ');
result[key] = splitCookiesString(value);
}
}
}
return result;
}

/*
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) {
const cookiesStrings = [];
let pos = 0;
let start;
let ch;
let lastComma;
let nextStart;
let 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;
}
2 changes: 1 addition & 1 deletion packages/middleware/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"lib": ["esnext", "dom", "dom.iterable"],
"target": "es2018",
"module": "commonjs",
"outDir": "dist",
Expand Down

0 comments on commit a38b0bc

Please sign in to comment.