From f2e299423a77e895e95da585e5a7d75f1f6929c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtte?= Date: Thu, 18 Apr 2024 18:30:25 +0200 Subject: [PATCH] Added bytes support for http (#691) --- crates/rune-modules/src/http.rs | 88 +++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 5 deletions(-) diff --git a/crates/rune-modules/src/http.rs b/crates/rune-modules/src/http.rs index 082b45c66..9b35c4d7e 100644 --- a/crates/rune-modules/src/http.rs +++ b/crates/rune-modules/src/http.rs @@ -48,9 +48,9 @@ //! } //! ``` -use rune::{Any, Module, Value, ContextError}; -use rune::runtime::{Bytes, Ref, Formatter, VmResult}; use rune::alloc::fmt::TryWrite; +use rune::runtime::{Bytes, Formatter, Ref, VmResult}; +use rune::{Any, ContextError, Module, Value}; /// A simple HTTP module for Rune. /// @@ -79,11 +79,13 @@ pub fn module(_stdio: bool) -> Result { module.function_meta(Response::text)?; module.function_meta(Response::json)?; + module.function_meta(Response::bytes)?; module.function_meta(Response::status)?; module.function_meta(RequestBuilder::send)?; module.function_meta(RequestBuilder::header)?; module.function_meta(RequestBuilder::body_bytes)?; + module.function_meta(RequestBuilder::fetch_mode_no_cors)?; module.function_meta(Error::string_display)?; module.function_meta(StatusCode::string_display)?; @@ -127,6 +129,17 @@ pub struct Response { impl Response { /// Get the response as text. + /// + /// ```rune,no_run + /// let client = http::Client::new(); + /// + /// let response = client.get("http://example.com") + /// .body_bytes(b"Hello World") + /// .send() + /// .await?; + /// + /// let response = response.text().await?; + /// ``` #[rune::function] async fn text(self) -> Result { let text = self.response.text().await?; @@ -140,6 +153,24 @@ impl Response { Ok(text) } + /// Get the response as bytes. + /// + /// ```rune,no_run + /// let client = http::Client::new(); + /// + /// let response = client.get("http://example.com") + /// .send() + /// .await?; + /// + /// let response = response.bytes().await?; + /// ``` + #[rune::function(vm_result)] + async fn bytes(self) -> Result { + let bytes = self.response.bytes().await?.to_vec().into_boxed_slice(); + let bytes = Bytes::from_slice(bytes).vm?; + Ok(bytes) + } + /// Get the status code of the response. #[rune::function] fn status(&self) -> StatusCode { @@ -173,7 +204,18 @@ pub struct RequestBuilder { } impl RequestBuilder { - /// Send the request being built. + /// Send the request and receive an answer from the server. + /// + /// ```rune,no_run + /// let client = http::Client::new(); + /// + /// let response = client.get("http://example.com") + /// .header("Accept", "text/html") + /// .send() + /// .await?; + /// + /// let response = response.text().await?; + /// ``` #[rune::function] async fn send(self) -> Result { let response = self.request.send().await?; @@ -181,6 +223,17 @@ impl RequestBuilder { } /// Modify a header in the request. + /// + /// ```rune,no_run + /// let client = http::Client::new(); + /// + /// let response = client.get("http://example.com") + /// .header("Accept", "text/html") + /// .send() + /// .await?; + /// + /// let response = response.text().await?; + /// ``` #[rune::function] fn header(self, key: &str, value: &str) -> Self { Self { @@ -188,6 +241,29 @@ impl RequestBuilder { } } + /// Disable CORS on fetching the request. + /// + /// This option is only effective with WebAssembly target. + /// The [request mode][mdn] will be set to 'no-cors'. + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode + /// + /// ```rune,no_run + /// let client = http::Client::new(); + /// + /// let response = client.get("http://example.com") + /// .fetch_mode_no_cors() + /// .send() + /// .await?; + /// + /// let response = response.text().await?; + /// ``` + #[rune::function] + fn fetch_mode_no_cors(self) -> Self { + Self { + request: self.request.fetch_mode_no_cors(), + } + } + /// Set the request body from bytes. /// /// ```rune,no_run @@ -240,7 +316,9 @@ impl Client { /// ``` #[rune::function] fn get(&self, url: &str) -> RequestBuilder { - RequestBuilder { request: self.client.get(url) } + RequestBuilder { + request: self.client.get(url), + } } /// Construct a builder to POST to the given `url`. @@ -271,7 +349,7 @@ impl Client { /// ```rune,no_run /// let response = http::get("http://worldtimeapi.org/api/ip").await?; /// let json = response.json().await?; -/// +/// /// let timezone = json["timezone"]; /// ``` #[rune::function]