From cd06adf6c894094f2ae9e1ffe0daab0d665df3bd Mon Sep 17 00:00:00 2001 From: Afonso Lage Date: Tue, 13 Feb 2024 09:31:25 -0300 Subject: [PATCH] Added CORS `Mode` property to `Request` on web (#52) Closes #51 - Add `Mode` to `Request` on wasm builds; - Add `Mode::Cors` as default; --------- Co-authored-by: Emil Ernerfeldt --- ehttp/src/lib.rs | 3 +++ ehttp/src/types.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++ ehttp/src/web.rs | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/ehttp/src/lib.rs b/ehttp/src/lib.rs index 96a5796..550b96e 100644 --- a/ehttp/src/lib.rs +++ b/ehttp/src/lib.rs @@ -75,6 +75,9 @@ pub async fn fetch_async(request: Request) -> Result { mod types; pub use types::{Error, Headers, PartialResponse, Request, Response, Result}; +#[cfg(target_arch = "wasm32")] +pub use types::Mode; + #[cfg(not(target_arch = "wasm32"))] mod native; #[cfg(not(target_arch = "wasm32"))] diff --git a/ehttp/src/types.rs b/ehttp/src/types.rs index 729a851..ed3febd 100644 --- a/ehttp/src/types.rs +++ b/ehttp/src/types.rs @@ -93,6 +93,39 @@ impl<'h> IntoIterator for &'h Headers { // ---------------------------------------------------------------------------- +/// Determine if cross-origin requests lead to valid responses. +/// Based on +#[cfg(target_arch = "wasm32")] +#[derive(Default, Clone, Copy, Debug)] +pub enum Mode { + /// If a request is made to another origin with this mode set, the result is an error. + SameOrigin = 0, + + /// The request will not include the Origin header in a request. + /// The server's response will be opaque, meaning that JavaScript code cannot access its contents + NoCors = 1, + + /// Includes an Origin header in the request and expects the server to respond with an + /// "Access-Control-Allow-Origin" header that indicates whether the request is allowed. + #[default] + Cors = 2, + + /// A mode for supporting navigation + Navigate = 3, +} + +#[cfg(target_arch = "wasm32")] +impl From for web_sys::RequestMode { + fn from(mode: Mode) -> Self { + match mode { + Mode::SameOrigin => web_sys::RequestMode::SameOrigin, + Mode::NoCors => web_sys::RequestMode::NoCors, + Mode::Cors => web_sys::RequestMode::Cors, + Mode::Navigate => web_sys::RequestMode::Navigate, + } + } +} + /// A simple HTTP request. #[derive(Clone, Debug)] pub struct Request { @@ -107,6 +140,10 @@ pub struct Request { /// ("Accept", "*/*"), … pub headers: Headers, + + /// Request mode used on fetch. Only available on wasm builds + #[cfg(target_arch = "wasm32")] + pub mode: Mode, } impl Request { @@ -118,6 +155,8 @@ impl Request { url: url.to_string(), body: vec![], headers: Headers::new(&[("Accept", "*/*")]), + #[cfg(target_arch = "wasm32")] + mode: Mode::default(), } } @@ -129,6 +168,8 @@ impl Request { url: url.to_string(), body: vec![], headers: Headers::new(&[("Accept", "*/*")]), + #[cfg(target_arch = "wasm32")] + mode: Mode::default(), } } @@ -143,6 +184,8 @@ impl Request { ("Accept", "*/*"), ("Content-Type", "text/plain; charset=utf-8"), ]), + #[cfg(target_arch = "wasm32")] + mode: Mode::default(), } } @@ -176,6 +219,8 @@ impl Request { url: url.to_string(), body: data, headers: Headers::new(&[("Accept", "*/*"), ("Content-Type", content_type.as_str())]), + #[cfg(target_arch = "wasm32")] + mode: Mode::default(), } } @@ -191,6 +236,8 @@ impl Request { url: url.to_string(), body: serde_json::to_string(body)?.into_bytes(), headers: Headers::new(&[("Accept", "*/*"), ("Content-Type", "application/json")]), + #[cfg(target_arch = "wasm32")] + mode: Mode::default(), }) } } diff --git a/ehttp/src/web.rs b/ehttp/src/web.rs index 94871dd..cb7d4c3 100644 --- a/ehttp/src/web.rs +++ b/ehttp/src/web.rs @@ -42,7 +42,7 @@ pub(crate) fn string_from_fetch_error(value: JsValue) -> String { pub(crate) async fn fetch_base(request: &Request) -> Result { let mut opts = web_sys::RequestInit::new(); opts.method(&request.method); - opts.mode(web_sys::RequestMode::Cors); + opts.mode(request.mode.into()); if !request.body.is_empty() { let body_bytes: &[u8] = &request.body;