From 3bb074c4980bab813a7ff19d5b2ccb1ac033edcc Mon Sep 17 00:00:00 2001 From: Max Hill Date: Fri, 30 Aug 2024 09:08:39 +0200 Subject: [PATCH 1/5] feat: Add remove cookie function to request module --- src/gleam/http/request.gleam | 19 +++++++++++++++++++ test/gleam/http/request_test.gleam | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/gleam/http/request.gleam b/src/gleam/http/request.gleam index b8d00ae..80c0303 100644 --- a/src/gleam/http/request.gleam +++ b/src/gleam/http/request.gleam @@ -1,3 +1,4 @@ +import gleam/bool import gleam/http.{type Header, type Method, type Scheme, Get} import gleam/http/cookie import gleam/list @@ -284,3 +285,21 @@ pub fn get_cookies(req) -> List(#(String, String)) { }) |> list.flatten() } + +/// Remove a cookie from a request +/// +/// Remove a cookie from the request. If no cookie is found return the request unchanged. +pub fn remove_cookie(req: Request(body), name: String) { + case list.key_pop(req.headers, "cookie") { + Ok(#(cookies_string, headers)) -> { + let new_cookies_string = + string.split(cookies_string, ";") + |> list.map(string.trim) + |> list.filter(fn(str) { string.starts_with(str, name) |> bool.negate }) + |> string.join("; ") + + Request(..req, headers: [#("cookie", new_cookies_string), ..headers]) + } + Error(_) -> req + } +} diff --git a/test/gleam/http/request_test.gleam b/test/gleam/http/request_test.gleam index d598c8f..b4f82a7 100644 --- a/test/gleam/http/request_test.gleam +++ b/test/gleam/http/request_test.gleam @@ -450,3 +450,27 @@ pub fn set_req_cookies_test() { |> request.get_header("cookie") |> should.equal(Ok("k1=v1; k2=v2")) } + +pub fn remove_cookie_from_request_test() { + let req = + request.new() + |> request.set_cookie("FIRST_COOKIE", "first") + |> request.set_cookie("SECOND_COOKIE", "second") + |> request.set_cookie("THIRD_COOKIE", "third") + + req + |> request.get_header("cookie") + |> should.be_ok + |> should.equal( + "FIRST_COOKIE=first; SECOND_COOKIE=second; THIRD_COOKIE=third", + ) + + let modified_req = + req + |> request.remove_cookie("SECOND_COOKIE") + + modified_req + |> request.get_header("cookie") + |> should.be_ok + |> should.equal("FIRST_COOKIE=first; THIRD_COOKIE=third") +} From eb1ca94929df151d3857dae8096c6a35275113fb Mon Sep 17 00:00:00 2001 From: Max Hill Date: Mon, 2 Sep 2024 19:55:26 +0200 Subject: [PATCH 2/5] docs: document that cookie is not removed from client --- src/gleam/http/request.gleam | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gleam/http/request.gleam b/src/gleam/http/request.gleam index 80c0303..fe34dca 100644 --- a/src/gleam/http/request.gleam +++ b/src/gleam/http/request.gleam @@ -1,4 +1,3 @@ -import gleam/bool import gleam/http.{type Header, type Method, type Scheme, Get} import gleam/http/cookie import gleam/list @@ -289,13 +288,14 @@ pub fn get_cookies(req) -> List(#(String, String)) { /// Remove a cookie from a request /// /// Remove a cookie from the request. If no cookie is found return the request unchanged. +/// This will not remove the cookie from the client. pub fn remove_cookie(req: Request(body), name: String) { case list.key_pop(req.headers, "cookie") { Ok(#(cookies_string, headers)) -> { let new_cookies_string = string.split(cookies_string, ";") |> list.map(string.trim) - |> list.filter(fn(str) { string.starts_with(str, name) |> bool.negate }) + |> list.filter(fn(str) { !string.starts_with(str, name) }) |> string.join("; ") Request(..req, headers: [#("cookie", new_cookies_string), ..headers]) From fff137f2b97c217e554346ce4a7613b1800138ad Mon Sep 17 00:00:00 2001 From: Max Hill Date: Tue, 3 Sep 2024 20:41:46 +0200 Subject: [PATCH 3/5] fix: handle case with partial cookie name --- src/gleam/http/request.gleam | 13 ++++++++++--- test/gleam/http/request_test.gleam | 13 +++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/gleam/http/request.gleam b/src/gleam/http/request.gleam index fe34dca..5994bea 100644 --- a/src/gleam/http/request.gleam +++ b/src/gleam/http/request.gleam @@ -1,5 +1,6 @@ import gleam/http.{type Header, type Method, type Scheme, Get} import gleam/http/cookie +import gleam/io import gleam/list import gleam/option.{type Option} import gleam/result @@ -294,9 +295,15 @@ pub fn remove_cookie(req: Request(body), name: String) { Ok(#(cookies_string, headers)) -> { let new_cookies_string = string.split(cookies_string, ";") - |> list.map(string.trim) - |> list.filter(fn(str) { !string.starts_with(str, name) }) - |> string.join("; ") + |> list.filter(fn(str) { + string.trim(str) + |> string.split_once("=") + // Keep cookie if name does not match + |> result.map(fn(tup) { tup.0 != name }) + // Don't do anything with malformed cookies + |> result.unwrap(True) + }) + |> string.join(";") Request(..req, headers: [#("cookie", new_cookies_string), ..headers]) } diff --git a/test/gleam/http/request_test.gleam b/test/gleam/http/request_test.gleam index b4f82a7..69b81dd 100644 --- a/test/gleam/http/request_test.gleam +++ b/test/gleam/http/request_test.gleam @@ -474,3 +474,16 @@ pub fn remove_cookie_from_request_test() { |> should.be_ok |> should.equal("FIRST_COOKIE=first; THIRD_COOKIE=third") } + +pub fn only_remove_matching_cookies_test() { + request.new() + |> request.set_cookie("FIRST_COOKIE", "first") + |> request.set_cookie("SECOND_COOKIE", "second") + |> request.set_cookie("THIRD_COOKIE", "third") + |> request.remove_cookie("SECOND") + |> request.get_header("cookie") + |> should.be_ok + |> should.equal( + "FIRST_COOKIE=first; SECOND_COOKIE=second; THIRD_COOKIE=third", + ) +} From c2ad48f70ae782dad33ab70c74a032854f14c111 Mon Sep 17 00:00:00 2001 From: Max Hill Date: Fri, 6 Sep 2024 15:37:09 +0200 Subject: [PATCH 4/5] fix: remove unused import --- src/gleam/http/request.gleam | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gleam/http/request.gleam b/src/gleam/http/request.gleam index 5994bea..a992433 100644 --- a/src/gleam/http/request.gleam +++ b/src/gleam/http/request.gleam @@ -1,6 +1,5 @@ import gleam/http.{type Header, type Method, type Scheme, Get} import gleam/http/cookie -import gleam/io import gleam/list import gleam/option.{type Option} import gleam/result From d471e09f81fa0a1cbec1bf10700a74d96df10730 Mon Sep 17 00:00:00 2001 From: Max Hill Date: Tue, 10 Sep 2024 21:32:56 +0200 Subject: [PATCH 5/5] docs: updates the changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0c757..4920787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## v.3.7.0 - 2024-09-10 +- The `gleam/http/request` module gains the `remove_cookie` function. + ## v3.6.2 - 2024-03-12 - The `gleam/http/service` module has been deprecated in favour of other