workers-rs icon indicating copy to clipboard operation
workers-rs copied to clipboard

Implement get_all function to return non-folding set-cookie headers

Open nakamura-shuta opened this issue 1 year ago • 5 comments

issue : https://github.com/cloudflare/workers-rs/issues/423

Define get_all in worker_sys::ext::headers::Headers and implement in worker::Headers

This PR implements the get_all function for Headers with the following approach:

  1. Define the get_all method in worker_sys::ext::headers::Headers
  2. Implement get_all in worker::Headers using the worker_sys implementation

Specification of the get_all function:

  • Retrieves all values of the Set-Cookie header
  • Returns the result as Result<Vec<String>>
  • Returns an error if the header name is not Set-Cookie
  • When there are multiple set-cookie headers, do not combine them

nakamura-shuta avatar Jul 18 '24 14:07 nakamura-shuta

Why limit only to set-cookie header?

kflansburg avatar Jul 18 '24 17:07 kflansburg

The workerd code I used as reference for implementation made an error when a header other than set-cookie was specified, so I implemented it as is.

https://github.com/cloudflare/workerd/blob/a265d5c22bf2a6bc6394aa54db517ff86d6c788c/src/workerd/api/http.c%2B%2B#L229-L242

nakamura-shuta avatar Jul 18 '24 23:07 nakamura-shuta

I see, I can ask internally about this.

If this is already implemented in the runtime, would it make sense to just add the getAll method to the wasm_bindgen Header extension type here https://github.com/cloudflare/workers-rs/blob/main/worker-sys/src/ext/headers.rs?

kflansburg avatar Jul 19 '24 11:07 kflansburg

@kflansburg

Yes, I think that is the simplest way. I implemented it that way. (Like other functions, such as “entries”.)

If you have any suggestions for improving this implementation, I would greatly appreciate your feedback. Thank you.

nakamura-shuta avatar Jul 22 '24 01:07 nakamura-shuta

Can we invoke the JavaScript getAll method via wasm-bindgen, rather than re-implementing it in Rust?

kflansburg avatar Aug 27 '24 11:08 kflansburg

@kflansburg

This looks great! Were you able to test this?

I created the following application under the example directory and verified its operation with curl. (Not git committed)

/// create sample application. examples/cookie/src/lib.rs
use worker::*;

// Main entry point for the worker
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
    // Set up a router and define a route for "/test_cookies"
    Router::with_data(())
        .get_async("/test_cookies", test_cookies)
        .run(req, env)
        .await
}

// Handler function for the "/test_cookies" route
async fn test_cookies(req: Request, _ctx: RouteContext<()>) -> Result<Response> {
    // Retrieve all Set-Cookie headers from the input request
    let input_cookies = req.headers().get_all("Set-Cookie")?;

    // Create a new response
    let mut res = Response::ok("Cookies processed")?;

    // Add the input Set-Cookie headers to the new response
    for cookie in &input_cookies {
        // Append each Set-Cookie header to the response
        res.headers_mut().append("Set-Cookie", cookie)?;
    }

    // Log the request and response headers for debugging
    console_log!("Request Set-Cookie headers: {:?}", input_cookies);
    console_log!("Response headers: {:?}", res.headers());

    // Return the response
    Ok(res)
}
# curl command in console

% curl 'http://localhost:8787/test_cookies' \
  -H 'Set-Cookie: a=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT' \
  -H 'Set-Cookie: b=2; Expires=Wed, 21 Oct 2015 07:28:00 GMT' \
  -v
* Host localhost:8787 was resolved.
> GET /test_cookies HTTP/1.1
> ・・・・・・・
> Set-Cookie: a=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT
> Set-Cookie: b=2; Expires=Wed, 21 Oct 2015 07:28:00 GMT
>
< HTTP/1.1 200 OK
< Content-Length: 17
< Content-Type: text/plain; charset=utf-8
< Set-Cookie: a=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT
< Set-Cookie: b=2; Expires=Wed, 21 Oct 2015 07:28:00 GMT
<
* Connection #0 to host localhost left intact
Cookies processed
# wrangler dev console

% cd workers-rs/examples/cookie
% npx wrangler dev

[wrangler:inf] Ready on http://localhost:8787
Request Set-Cookie headers: ["a=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT", "b=2; Expires=Wed, 21 Oct 2015 07:28:00 GMT"]
Response headers: Headers {
content-type = text/plain; charset=utf-8
set-cookie = a=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT
set-cookie = b=2; Expires=Wed, 21 Oct 2015 07:28:00 GMT
}
[wrangler:inf] GET /test_cookies 200 OK (12ms)

nakamura-shuta avatar Sep 02 '24 01:09 nakamura-shuta