Search code examples
sveltestrapisveltekit

SVELTE set multiple Http cookies in one request headers


I'm facing an issue since svelte last update. When I try to add multiple set-cookie in one request, only the first one is executed. I'm searching for 5 days, and I didn't find any solution.

Config

Frontend - SvelteKit v1.0.0-next.234 Backend - Strapi 3.6.1 (v4.x.x not working with mongoDb if I understand well) Db - mongo

What worked before Svelte update

I call my login endpoint with my credentials (username, password), and wait for the jwt token response. When I receive it, I put it within other elements in my http request headers. In the hook.js file, I parse this header cookie and add it to my request.locals. Therefore, I can use my request locals within the getSession() method of the hooks.

Login.json.js endpoint

... all the query logic
const user = await login();
// ==> I get the jwt token

const cookieOptions = {
 Secure: secure ? 'Secure;' : '',
 httpOnly: true,
 sameSite: sameSite,
 path: "/",
 maxAge: 60 * 60 * 24 * 7
}
const setUsername = cookie.serialize(`${COOKIE_NAME}`, user.user.username, cookieOptions);
const setJwt = cookie.serialize("jwt", user.jwt, cookieOptions);
const setCompId = cookie.serialize("_cId", user.user.company._id, cookieOptions); 


// what worked before, but stop working after svelte framework update
const headers = {        
 'Set-Cookie': [setUsername, setJwt, setCompId]
}

// what I do know to find a way to solve it
let headers = new Headers();
headers.append('Set-Cookie',setUsername);
headers.append('Set-Cookie',setJwt);
headers.append('Set-Cookie',setCompId);

// the response
return {
  body: {
   user
  },
 headers,
 status: 200
 }

I've tried to put a plain text cookie, something like this :

cookiename=myUserName; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict, jwt=xxx.xxx.Xxx; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict, _cId=sjckjsdhfjkqsdhfjk; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict

Only the first cookie is set in the header and in the browser.

hook.js

In my hook file, I had to change the object received by the handle function du to Svelte update

From this

export async function handle({request,resolve}){
 const cookies = cookie.parse(request.headers.cookie || "");
...
}

To this

export async function handle({event,resolve}){
 let cookies = event.request.headers.get("cookie")
...
}

The problem is that I only have one cookie value instead of 3.

I didn't found the solution. I think I can pass all my arguments within the first cookie value, in my login response, but, I think it's not a good idea.

I'm asking for help, because I can't move on my project. My dashboard pages call depends on these 3 elements gathering first.

Thank you all

update 1

I've changed the code has suggested by Thommas

const headers = new Headers()
headers.append('Set-Cookie', [setUsername, setJwt, setCompId].join(','))

When I console.log the headers it's ok, I get my 3 elements separated with a comma.

console.log(headers.get('Set-Cookie'));
// => result string : 
/*
MYCOOKIENAME=ItIsOk; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict,jwt=xxx.xxxx.xxxx.xxxx.Xxx.etc...; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict,_cId=ItIsOk; Max-Age=604800; Path=/; HttpOnly; SameSite=Strict
*/

But, when I look at the request headers in the hooks.js, I still get the first one.

console.log("==>\n",event.request.headers,"\n<==\n")

// result 
{
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',
  'cache-control': 'no-cache',
  connection: 'keep-alive',
  cookie: 'MYCOOKIENAME=ItIsOk',
  host: 'localhost:3000',
  pragma: 'no-cache',
  referer: 'http://localhost:3000/login',
  'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"macOS"',
  'sec-fetch-dest': 'document',
  'sec-fetch-mode': 'navigate',
  'sec-fetch-site': 'same-origin',
  'sec-fetch-user': '?1',
  'upgrade-insecure-requests': '1',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
} 

May be my return object is wrong.

return {
 body: {
  user
 },
 headers,
 status: 200
 }
}

I you have any idea ! I'll continue working on this issue, because I totaly blocked !


Solution

  • This was discussed in

    https://github.com/sveltejs/kit/issues/3460

    you can use response.headers.append(headerName, headerValue) to add a header without overwriting existing ones. Just call this for every set-cookie you need.