Skip to content

add_response_header will override existing Set-Cookie headers #5541

@ebina4yaka

Description

@ebina4yaka

Problem

In fullstack-core/src/streaming.rs, the add_response_header mehod uses insert method to add headers to the response. However, insert method replaces any existing header with the same name, which breaks multi-valued headers like Set-Cookie.

pub fn add_response_header(
&self,
key: impl Into<http::header::HeaderName>,
value: impl Into<http::header::HeaderValue>,
) {
let mut lock = self.lock.write();
if let Some(headers) = lock.response_headers.as_mut() {
headers.insert(key.into(), value.into());
}
}

Steps To Reproduce

Steps to reproduce the behavior:

  • In a fullstack Dioxus app, call at server function
ctx.add_response_header(
    http::header::SET_COOKIE,
    http::HeaderValue::from_str(
        "name=example_1",
    )
    .unwrap(),
);
ctx.add_response_header(
    http::header::SET_COOKIE,
    http::HeaderValue::from_str(
        "name=example_2",
    )
    .unwrap(),
);
  • Only last set Set-Cookie header ("name=example_2") appears in the response.

Expected behavior

At least regarding the Set-Cookie response header, I believe it's preferable to be able to set and return multiple values.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie

https://datatracker.ietf.org/doc/html/rfc6265#section-3

Screenshots

N/A

Environment:

  • Dioxus version: v0.7.9
  • Rust version:
  • OS info: Windows 11
  • App platform: fullstack web

Questionnaire

I would like to fix and I have a solution.

In the add_response_header method, I think modify it to treat Set-Cookie headers as a special case by replacing the insert method with the append method when the argument contains a Set-Cookie header.

/// Add a header to the response. This will be sent to the client when the response is committed.
/// Set-Cookie headers will be appended to any existing Set-Cookie headers (compliance with RFC 6265),
/// while all other headers will overwrite any existing header with the same name.
pub fn add_response_header(
    &self,
    key: impl Into<http::header::HeaderName>,
    value: impl Into<http::header::HeaderValue>,
) {
    let mut lock = self.lock.write();
    if let Some(headers) = lock.response_headers.as_mut() {
        let key_into = key.into();
        if key_into == http::header::SET_COOKIE {
            headers.append(key_into, value.into());
        } else {
            headers.insert(key_into, value.into());
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions