From 51c66e5e72f0e6cd08dc1b2080eb73c2cce6fb73 Mon Sep 17 00:00:00 2001
From: Maccesch <maccesch@synphonyte.com>
Date: Mon, 29 Jan 2024 18:05:06 +0000
Subject: [PATCH] updated tests to accomodate use_cookie and added possibility
 to get your own cookie header value

---
 .github/workflows/ci.yml    |  47 +++-----------
 .github/workflows/tests.yml |   8 ++-
 src/use_cookie.rs           | 124 ++++++++++++++++++++++++++++--------
 3 files changed, 110 insertions(+), 69 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6ad089d..38f8cde 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,10 +31,14 @@ jobs:
         run: cargo fmt --check
       - name: Clippy
         run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
-      - name: Run tests
-        run: cargo test --all-features
+      - name: Run tests (general)
+        run: cargo test --features math,docs,ssr,prost,serde
+      - name: Run tests (axum)
+        run: cargo test --features math,docs,ssr,prost,serde,axum --doc use_cookie::use_cookie
+      - name: Run tests (actix)
+        run: cargo test --features math,docs,ssr,prost,serde,actix --doc use_cookie::use_cookie
 
-#### mdbook
+      #### mdbook
       - name: Install mdbook I
         uses: taiki-e/install-action@v2
         with:
@@ -59,7 +63,7 @@ jobs:
       - name: Deploy book to github pages
         id: deployment
         uses: actions/deploy-pages@v2
-##### mdbook end
+      ##### mdbook end
 
       - name: Publish crate leptos-use
         uses: katyo/publish-crates@v2
@@ -76,38 +80,3 @@ jobs:
           -F RELEASE.md
           -t "Version $RELEASE_VERSION"
           ${GITHUB_REF#refs/*/}
-
-#  coverage:
-#    name: Coverage
-#    runs-on: ubuntu-latest
-#
-#    steps:
-#      - name: Checkout sources
-#        uses: actions/checkout@v2
-#
-#      - name: Install rust
-#        uses: actions-rs/toolchain@v1
-#        with:
-#          toolchain: stable
-#          profile: minimal
-#          override: true
-#
-#      - name: Cache
-#        uses: Swatinem/rust-cache@v1
-#
-#      - name: Install cargo-tarpaulin
-#        uses: actions-rs/cargo@v1
-#        with:
-#          command: install
-#          args: cargo-tarpaulin
-#
-#      - name: Run cargo tarpaulin
-#        uses: actions-rs/cargo@v1
-#        with:
-#          command: tarpaulin
-#          args: --output-dir coverage --out Lcov
-#
-#      - name: Publish to Coveralls
-#        uses: coverallsapp/github-action@master
-#        with:
-#          github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index f5500fb..d43d0b4 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -24,5 +24,9 @@ jobs:
         run: cargo fmt --check
       - name: Clippy
         run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
-      - name: Run tests
-        run: cargo test --all-features
+      - name: Run tests (general)
+        run: cargo test --features math,docs,ssr,prost,serde
+      - name: Run tests (axum)
+        run: cargo test --features math,docs,ssr,prost,serde,axum --doc use_cookie::use_cookie
+      - name: Run tests (actix)
+        run: cargo test --features math,docs,ssr,prost,serde,actix --doc use_cookie::use_cookie
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index 1cec388..438a8c4 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -1,4 +1,6 @@
 use cookie::Cookie;
+use default_struct_builder::DefaultBuilder;
+use std::rc::Rc;
 
 /// Get a cookie by name, for both SSR and CSR
 ///
@@ -39,39 +41,43 @@ use cookie::Cookie;
 ///
 /// > If you're using `axum` you have to enable the `"axum"` feature in your Cargo.toml.
 /// > In case it's `actix-web` enable the feature `"actix"`.
+///
+/// ### Bring your own header
+///
+/// In case you're neither using Axum nor Actix, or the default implementation is not to your liking,
+/// you can provide your own way of reading the cookie header value.
+///
+/// ```
+/// # use leptos::*;
+/// # use leptos_use::{use_cookie_with_options, UseCookieOptions};
+/// #
+/// # #[component]
+/// # fn Demo() -> impl IntoView {
+/// use_cookie_with_options("auth", UseCookieOptions::default().ssr_cookies_header_getter(|| {
+///     #[cfg(feature = "ssr")]
+///     {
+///         "Somehow get the value of the cookie header as a string".to_owned()
+///     }
+/// }));
+/// # view! {}
+/// # }
+/// ```
 pub fn use_cookie(cookie_name: &str) -> Option<Cookie<'static>> {
+    use_cookie_with_options(cookie_name, UseCookieOptions::default())
+}
+
+/// Version of [`use_cookie`] that takes [`UseCookieOptions`].
+pub fn use_cookie_with_options(
+    cookie_name: &str,
+    options: UseCookieOptions,
+) -> Option<Cookie<'static>> {
     let cookies;
+
     #[cfg(feature = "ssr")]
     {
-        use leptos::expect_context;
-
-        #[cfg(feature = "actix")]
-        const COOKIE: http0_2::HeaderName = http0_2::header::COOKIE;
-        #[cfg(feature = "axum")]
-        const COOKIE: http1::HeaderName = http1::header::COOKIE;
-
-        #[cfg(feature = "actix")]
-        type HeaderValue = http0_2::HeaderValue;
-        #[cfg(feature = "axum")]
-        type HeaderValue = http1::HeaderValue;
-
-        let headers;
-        #[cfg(feature = "actix")]
-        {
-            headers = expect_context::<actix_web::HttpRequest>().headers().clone();
-        }
-        #[cfg(feature = "axum")]
-        {
-            headers = expect_context::<http1::request::Parts>().headers;
-        }
-        cookies = headers
-            .get(COOKIE)
-            .cloned()
-            .unwrap_or_else(|| HeaderValue::from_static(""))
-            .to_str()
-            .unwrap_or_default()
-            .to_owned();
+        cookies = (options.ssr_cookies_header_getter)();
     }
+
     #[cfg(not(feature = "ssr"))]
     {
         use wasm_bindgen::JsCast;
@@ -86,3 +92,65 @@ pub fn use_cookie(cookie_name: &str) -> Option<Cookie<'static>> {
         .find(|cookie| cookie.name() == cookie_name)
         .map(|cookie| cookie.into_owned())
 }
+
+/// Options for [`use_cookie_with_options`].
+#[derive(Clone, DefaultBuilder)]
+pub struct UseCookieOptions {
+    /// Getter function to return the string value of the cookie header.
+    /// When you use one of the features "axum" or "actix" there's a valid default implementation provided.
+    ssr_cookies_header_getter: Rc<dyn Fn() -> String>,
+}
+
+impl Default for UseCookieOptions {
+    #[allow(dead_code)]
+    fn default() -> Self {
+        Self {
+            ssr_cookies_header_getter: Rc::new(move || {
+                #[cfg(feature = "ssr")]
+                {
+                    #[cfg(any(feature = "axum", feature = "actix"))]
+                    use leptos::expect_context;
+
+                    #[cfg(all(feature = "actix", feature = "axum"))]
+                    compile_error!("You cannot enable only one of features \"actix\" and \"axum\" at the same time");
+
+                    #[cfg(feature = "actix")]
+                    const COOKIE: http0_2::HeaderName = http0_2::header::COOKIE;
+                    #[cfg(feature = "axum")]
+                    const COOKIE: http1::HeaderName = http1::header::COOKIE;
+
+                    #[cfg(feature = "actix")]
+                    type HeaderValue = http0_2::HeaderValue;
+                    #[cfg(feature = "axum")]
+                    type HeaderValue = http1::HeaderValue;
+
+                    #[cfg(any(feature = "axum", feature = "actix"))]
+                    let headers;
+                    #[cfg(feature = "actix")]
+                    {
+                        headers = expect_context::<actix_web::HttpRequest>().headers().clone();
+                    }
+                    #[cfg(feature = "axum")]
+                    {
+                        headers = expect_context::<http1::request::Parts>().headers;
+                    }
+
+                    #[cfg(all(not(feature = "axum"), not(feature = "actix")))]
+                    {
+                        leptos::logging::warn!("If you're using use_cookie without the feature `axum` or `actix` enabled, you should provide the option `ssr_cookies_header_getter`");
+                        "".to_owned()
+                    }
+
+                    #[cfg(any(feature = "axum", feature = "actix"))]
+                    headers
+                        .get(COOKIE)
+                        .cloned()
+                        .unwrap_or_else(|| HeaderValue::from_static(""))
+                        .to_str()
+                        .unwrap_or_default()
+                        .to_owned()
+                }
+            }),
+        }
+    }
+}