wasm: Add request body in the form of Bytes (#696)
* Add body bytes * Add example and header creation code
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							b24b0be461
						
					
				
				
					commit
					f6f81f9cc1
				
			| @@ -1,3 +1,59 @@ | ||||
| /// dox | ||||
| #[derive(Debug)] | ||||
| pub struct Body(()); | ||||
| use bytes::Bytes; | ||||
| use std::fmt; | ||||
|  | ||||
| /// The body of a `Request`. | ||||
| /// | ||||
| /// In most cases, this is not needed directly, as the | ||||
| /// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows | ||||
| /// passing many things (like a string or vector of bytes). | ||||
| /// | ||||
| /// [builder]: ./struct.RequestBuilder.html#method.body | ||||
| pub struct Body(Bytes); | ||||
|  | ||||
| impl Body { | ||||
|     pub(crate) fn bytes(&self) -> &Bytes { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Bytes> for Body { | ||||
|     #[inline] | ||||
|     fn from(bytes: Bytes) -> Body { | ||||
|         Body(bytes) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Vec<u8>> for Body { | ||||
|     #[inline] | ||||
|     fn from(vec: Vec<u8>) -> Body { | ||||
|         Body(vec.into()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static [u8]> for Body { | ||||
|     #[inline] | ||||
|     fn from(s: &'static [u8]) -> Body { | ||||
|         Body(Bytes::from_static(s)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for Body { | ||||
|     #[inline] | ||||
|     fn from(s: String) -> Body { | ||||
|         Body(s.into()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static str> for Body { | ||||
|     #[inline] | ||||
|     fn from(s: &'static str) -> Body { | ||||
|         s.as_bytes().into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Debug for Body { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         f.debug_struct("Body").finish() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| use std::future::Future; | ||||
| use http::Method; | ||||
| use js_sys::Uint8Array; | ||||
| use std::future::Future; | ||||
| use wasm_bindgen::UnwrapThrowExt as _; | ||||
|  | ||||
| use crate::IntoUrl; | ||||
| use super::{Request, RequestBuilder, Response}; | ||||
| use crate::IntoUrl; | ||||
|  | ||||
| /// dox | ||||
| #[derive(Clone, Debug)] | ||||
| @@ -91,7 +92,10 @@ impl Client { | ||||
|         RequestBuilder::new(self.clone(), req) | ||||
|     } | ||||
|  | ||||
|     pub(super) fn execute_request(&self, req: Request) -> impl Future<Output = crate::Result<Response>> { | ||||
|     pub(super) fn execute_request( | ||||
|         &self, | ||||
|         req: Request, | ||||
|     ) -> impl Future<Output = crate::Result<Response>> { | ||||
|         fetch(req) | ||||
|     } | ||||
| } | ||||
| @@ -107,12 +111,21 @@ async fn fetch(req: Request) -> crate::Result<Response> { | ||||
|  | ||||
|     for (name, value) in req.headers() { | ||||
|         js_headers | ||||
|             .append(name.as_str(), value.to_str().map_err(crate::error::builder)?) | ||||
|             .append( | ||||
|                 name.as_str(), | ||||
|                 value.to_str().map_err(crate::error::builder)?, | ||||
|             ) | ||||
|             .map_err(crate::error::wasm) | ||||
|             .map_err(crate::error::builder)?; | ||||
|     } | ||||
|     init.headers(&js_headers.into()); | ||||
|  | ||||
|     if let Some(body) = req.body() { | ||||
|         let body_bytes: &[u8] = body.bytes(); | ||||
|         let body_array: Uint8Array = body_bytes.into(); | ||||
|         init.body(Some(&body_array.into())); | ||||
|     } | ||||
|  | ||||
|     let js_req = web_sys::Request::new_with_str_and_init(req.url().as_str(), &init) | ||||
|         .map_err(crate::error::wasm) | ||||
|         .map_err(crate::error::builder)?; | ||||
| @@ -160,5 +173,4 @@ impl ClientBuilder { | ||||
|     pub fn build(self) -> Result<Client, crate::Error> { | ||||
|         Ok(Client(())) | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| use http::HttpTryFrom; | ||||
| use std::fmt; | ||||
|  | ||||
| use http::{Method, HeaderMap}; | ||||
| use http::Method; | ||||
| use url::Url; | ||||
|  | ||||
| use super::{Body, Client, Response}; | ||||
| use crate::header::{HeaderMap, HeaderName, HeaderValue}; | ||||
|  | ||||
| /// A request which can be executed with `Client::execute()`. | ||||
| pub struct Request { | ||||
| @@ -83,7 +85,6 @@ impl RequestBuilder { | ||||
|         RequestBuilder { client, request } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /// Set the request body. | ||||
|     pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder { | ||||
|         if let Ok(ref mut req) = self.request { | ||||
| @@ -92,6 +93,30 @@ impl RequestBuilder { | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     /// Add a `Header` to this Request. | ||||
|     pub fn header<K, V>(mut self, key: K, value: V) -> RequestBuilder | ||||
|     where | ||||
|         HeaderName: HttpTryFrom<K>, | ||||
|         HeaderValue: HttpTryFrom<V>, | ||||
|     { | ||||
|         let mut error = None; | ||||
|         if let Ok(ref mut req) = self.request { | ||||
|             match <HeaderName as HttpTryFrom<K>>::try_from(key) { | ||||
|                 Ok(key) => match <HeaderValue as HttpTryFrom<V>>::try_from(value) { | ||||
|                     Ok(value) => { | ||||
|                         req.headers_mut().append(key, value); | ||||
|                     } | ||||
|                     Err(e) => error = Some(crate::error::builder(e.into())), | ||||
|                 }, | ||||
|                 Err(e) => error = Some(crate::error::builder(e.into())), | ||||
|             }; | ||||
|         } | ||||
|         if let Some(err) = error { | ||||
|             self.request = Err(err); | ||||
|         } | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     /// Constructs the Request and sends it to the target URL, returning a | ||||
|     /// future Response. | ||||
|     /// | ||||
|   | ||||
		Reference in New Issue
	
	Block a user