Created
July 30, 2018 17:14
-
-
Save DoumanAsh/3b7e8d1f878653402ba75cd31cf409a2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pub struct Builder { | |
| parts: http::request::Parts, | |
| } | |
| impl Builder { | |
| ///Starts process of creating request. | |
| pub fn new(uri: hyper::Uri, method: hyper::Method) -> Self { | |
| let parts = http::request::Parts { | |
| method, | |
| uri, | |
| version: http::Version::default(), | |
| headers: http::HeaderMap::default(), | |
| extensions: http::Extensions::default() | |
| }; | |
| Self { | |
| parts | |
| } | |
| } | |
| ///Gets reference to headers. | |
| pub fn headers(&mut self) -> &mut http::HeaderMap { | |
| &mut self.parts.headers | |
| } | |
| ///Sets new header to request. | |
| /// | |
| ///If header exists, it replaces it. | |
| /// | |
| ///# Panics | |
| /// | |
| ///- On attempt to set invalid header value. | |
| pub fn set_header<K: header::IntoHeaderName, V>(mut self, key: K, value: V) -> Self where HeaderValue: HttpTryFrom<V> { | |
| let value = match HeaderValue::try_from(value) { | |
| Ok(value) => value, | |
| Err(_) => panic!("Attempt to set invalid header"), | |
| }; | |
| let _ = self.headers().insert(key, value); | |
| self | |
| } | |
| #[inline] | |
| ///Sets new header to request, only if it wasn't set previously. | |
| /// | |
| ///# Panics | |
| /// | |
| ///- On attempt to set invalid header value. | |
| pub fn set_header_if_none<K: header::AsHeaderName, V>(mut self, key: K, value: V) -> Self where HeaderValue: HttpTryFrom<V> { | |
| match self.headers().entry(key).expect("Valid header name") { | |
| http::header::Entry::Vacant(entry) => match HeaderValue::try_from(value) { | |
| Ok(value) => { | |
| entry.insert(value); | |
| }, | |
| Err(_) => panic!("Attempt to set invalid header value") | |
| }, | |
| _ => (), | |
| } | |
| self | |
| } | |
| #[inline] | |
| ///Sets `Content-Length` header. | |
| /// | |
| ///It replaces previous one, if there was any. | |
| pub fn content_len(self, len: u64) -> Self { | |
| self.set_header(http::header::CONTENT_LENGTH, len) | |
| } | |
| ///Adds authentication header. | |
| pub fn basic_auth<U: fmt::Display, P: fmt::Display>(mut self, username: U, password: Option<P>) -> Self { | |
| const BASIC: &'static str = "basic "; | |
| let auth = match password { | |
| Some(password) => format!("{}:{}", username, password), | |
| None => format!("{}:", username) | |
| }; | |
| let encode_len = BASE64.encode_len(auth.as_bytes().len()); | |
| let header_value = unsafe { | |
| let mut header_value = bytes::BytesMut::with_capacity(encode_len + BASIC.as_bytes().len()); | |
| header_value.put_slice(BASIC.as_bytes()); | |
| BASE64.encode_mut(auth.as_bytes(), &mut header_value.bytes_mut()[..encode_len]); | |
| header_value.advance_mut(encode_len); | |
| http::header::HeaderValue::from_shared_unchecked(header_value.freeze()) | |
| }; | |
| let _ = self.headers().insert(http::header::AUTHORIZATION, header_value); | |
| self | |
| } | |
| ///Sets request's query by overwriting existing one, if any. | |
| /// | |
| ///# Panics | |
| /// | |
| ///- If unable to encode data. | |
| ///- If URI creation fails | |
| pub fn query<Q: Serialize>(mut self, query: Q) -> Self { | |
| let mut uri_parts = self.parts.uri.into_parts(); | |
| let path = uri_parts.path_and_query; | |
| let mut buffer = bytes::BytesMut::new().writer(); | |
| let query = serde_urlencoded::to_string(&query).expect("To url-encode"); | |
| let _ = match path { | |
| Some(path) => write!(buffer, "{}?{}", path.path(), query), | |
| None => write!(buffer, "/?{}", query), | |
| }; | |
| uri_parts.path_and_query = Some(http::uri::PathAndQuery::from_shared(buffer.into_inner().freeze()).expect("To create path and query")); | |
| self.parts.uri = match http::Uri::from_parts(uri_parts) { | |
| Ok(uri) => uri, | |
| Err(error) => panic!("Unable to set query for URI: {}", error) | |
| }; | |
| self | |
| } | |
| ///Creates request with specified body. | |
| pub fn body<B: Into<hyper::Body>>(self, body: B) -> Request { | |
| let inner = HyperRequest::from_parts(self.parts, body.into()); | |
| Request { | |
| inner | |
| } | |
| } | |
| ///Creates request with Form payload. | |
| pub fn form<F: Serialize>(self, body: F) -> Result<Request, serde_urlencoded::ser::Error> { | |
| let body = serde_urlencoded::to_string(&body)?; | |
| Ok(self.set_header_if_none(header::CONTENT_TYPE, "application/x-www-form-urlencoded").body(body)) | |
| } | |
| ///Creates request with JSON payload. | |
| pub fn json<J: Serialize>(self, body: J) -> serde_json::Result<Request> { | |
| let mut buffer = bytes::BytesMut::new().writer(); | |
| let _ = serde_json::to_writer(&mut buffer, &body)?; | |
| let body = buffer.into_inner().freeze(); | |
| Ok(self.set_header_if_none(header::CONTENT_TYPE, "application/json").body(body)) | |
| } | |
| ///Creates request with no body. | |
| /// | |
| ///Explicitly sets `Content-Length` to 0 | |
| pub fn empty(self) -> Request { | |
| self.content_len(0).body(hyper::Body::empty()) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment