Skip to content

toResponse overwrites multiple Set-Cookie headers #118

@rastislavcore

Description

@rastislavcore

Summary

When an endpoint sets multiple cookies (e.g. via ctx.setCookie()), the Response built by toResponse() ends up with only one Set-Cookie header. The rest are dropped, so the browser never receives them (e.g. session cookie is lost and the user does not appear logged in).

Cause

In to-response (and the built dist/to-response.mjs), headers are merged by iterating and calling headers.set(key, value). For repeated header names, Headers#set() replaces the previous value, so only the last Set-Cookie is kept.

Places affected:

  1. Response branch (when data instanceof Response): init.headers.forEach((value, key) => { data.headers.set(key, value); }) overwrites previous set-cookie values.
  2. isJSONResponse branch: the three loops that copy routerResponse.headers, data.headers, and init.headers all use headers.set(key, value) in the same way.

HTTP allows multiple Set-Cookie headers (one per cookie). The Fetch Headers API allows multiple values for the same name only when using append(), not set().

Impact

  • Auth/session flows that set several cookies (e.g. session token + session_data + dont_remember) only send one cookie to the client.
  • Typically the session token is set first and a cache cookie last, so the last one survives and the session cookie is lost → user is not logged in after sign-in.

Suggested fix

When copying/merging headers, use append(key, value) for the set-cookie header name and set(key, value) for others (e.g. a small copyHeaders(target, source) helper used in all merge sites in to-response). That preserves every Set-Cookie line in the final Response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions