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

Override cookie encode #10055

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
- eric-burel
- ericchernuka
- esamattis
- Evanion
- evanwinter
- everdimension
- exegeteio
Expand Down
32 changes: 32 additions & 0 deletions packages/remix-server-runtime/__tests__/cookies-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,38 @@ describe("cookies", () => {
);
});
});

describe("encode/decode options", () => {
it("Will not Base64 encode/decode the cookie if `encode` and `decode` are set to custom functions", async () => {
let testValue = { hello: "world" };
let cookie = createCookie("my-cookie", {
encode: (value) => JSON.stringify(value),
decode: (value) => JSON.parse(value),
});
let setCookie = await cookie.serialize(testValue);

expect(setCookie).toBe("my-cookie=" + JSON.stringify(testValue));
});

it("Will not allow `encode` and `decode` to be set at the same time as `secrets`", async () => {
let secrets = ["foo"];
let encode = (value) => JSON.stringify(value);

expect(() => {
createCookie("my-cookie", { secrets, encode });
}).toThrowErrorMatchingInlineSnapshot(
"sign is not supported with encode option"
);

let decode = (value) => JSON.parse(value);

expect(() => {
createCookie("my-cookie", { secrets, decode });
}).toThrowErrorMatchingInlineSnapshot(
"unsign is not supported with decode option"
);
});
});
});

function spyConsole() {
Expand Down
27 changes: 21 additions & 6 deletions packages/remix-server-runtime/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,30 @@ export const createCookieFactory =
},
async parse(cookieHeader, parseOptions) {
if (!cookieHeader) return null;
if (secrets.length > 0 && !!parseOptions?.decode)
throw new Error("unsign is not supported with decode option");
let shouldEncode = !parseOptions?.decode;
let cookies = parse(cookieHeader, { ...options, ...parseOptions });
return name in cookies
? cookies[name] === ""
? ""
: await decodeCookieValue(unsign, cookies[name], secrets)
: await decodeCookieValue(
unsign,
cookies[name],
secrets,
shouldEncode
)
: null;
},
async serialize(value, serializeOptions) {
if (secrets.length > 0 && !!serializeOptions?.encode)
throw new Error("sign is not supported with encode option");
let shouldEncode = !serializeOptions?.encode;
return serialize(
name,
value === "" ? "" : await encodeCookieValue(sign, value, secrets),
value === ""
? ""
: await encodeCookieValue(sign, value, secrets, shouldEncode),
{
...options,
...serializeOptions,
Expand Down Expand Up @@ -149,9 +162,10 @@ export const isCookie: IsCookieFunction = (object): object is Cookie => {
async function encodeCookieValue(
sign: SignFunction,
value: any,
secrets: string[]
secrets: string[],
shouldEncode: boolean
): Promise<string> {
let encoded = encodeData(value);
let encoded = shouldEncode ? encodeData(value) : value;

if (secrets.length > 0) {
encoded = await sign(encoded, secrets[0]);
Expand All @@ -163,7 +177,8 @@ async function encodeCookieValue(
async function decodeCookieValue(
unsign: UnsignFunction,
value: string,
secrets: string[]
secrets: string[],
shouldDecode: boolean
): Promise<any> {
if (secrets.length > 0) {
for (let secret of secrets) {
Expand All @@ -176,7 +191,7 @@ async function decodeCookieValue(
return null;
}

return decodeData(value);
return shouldDecode ? decodeData(value) : value;
}

function encodeData(value: any): string {
Expand Down