style(rust): Format all Rust code with rustfmt
Change-Id: Iab7e00cc26a4f9727d3ab98691ef379921a33052 Reviewed-on: https://cl.tvl.fyi/c/depot/+/5240 Tested-by: BuildkiteCI Reviewed-by: kanepyork <rikingcoding@gmail.com> Reviewed-by: Profpatsch <mail@profpatsch.de> Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
parent
3318982f81
commit
3d8ee62087
42 changed files with 1253 additions and 876 deletions
|
|
@ -33,9 +33,12 @@
|
|||
//! use crimp::Request;
|
||||
//!
|
||||
//! let response = Request::get("http://httpbin.org/get")
|
||||
//! .user_agent("crimp test suite").unwrap()
|
||||
//! .send().unwrap()
|
||||
//! .as_string().unwrap();
|
||||
//! .user_agent("crimp test suite")
|
||||
//! .unwrap()
|
||||
//! .send()
|
||||
//! .unwrap()
|
||||
//! .as_string()
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! println!("Status: {}\nBody: {}", response.status, response.body);
|
||||
//! # assert_eq!(response.status, 200);
|
||||
|
|
@ -54,10 +57,9 @@
|
|||
//!
|
||||
//! All optional features are enabled by default.
|
||||
//!
|
||||
//! * `json`: Adds `Request::json` and `Response::as_json` methods
|
||||
//! which can be used for convenient serialisation of
|
||||
//! request/response bodies using `serde_json`. This feature adds a
|
||||
//! dependency on the `serde` and `serde_json` crates.
|
||||
//! * `json`: Adds `Request::json` and `Response::as_json` methods which can be used for convenient
|
||||
//! serialisation of request/response bodies using `serde_json`. This feature adds a dependency on
|
||||
//! the `serde` and `serde_json` crates.
|
||||
//!
|
||||
//! ## Initialisation
|
||||
//!
|
||||
|
|
@ -72,32 +74,42 @@
|
|||
|
||||
extern crate curl;
|
||||
|
||||
#[cfg(feature = "json")] extern crate serde;
|
||||
#[cfg(feature = "json")] extern crate serde_json;
|
||||
#[cfg(feature = "json")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "json")]
|
||||
extern crate serde_json;
|
||||
|
||||
pub use curl::init;
|
||||
|
||||
use curl::easy::{Auth, Easy, Form, List, Transfer, ReadError, WriteError};
|
||||
use curl::easy::{Auth, Easy, Form, List, ReadError, Transfer, WriteError};
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::string::{FromUtf8Error, ToString};
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "json")] use serde::Serialize;
|
||||
#[cfg(feature = "json")] use serde::de::DeserializeOwned;
|
||||
#[cfg(feature = "json")]
|
||||
use serde::de::DeserializeOwned;
|
||||
#[cfg(feature = "json")]
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// HTTP method to use for the request.
|
||||
enum Method {
|
||||
Get, Post, Put, Patch, Delete
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Patch,
|
||||
Delete,
|
||||
}
|
||||
|
||||
/// Certificate types for client-certificate key pairs.
|
||||
pub enum CertType {
|
||||
P12, PEM, DER
|
||||
P12,
|
||||
PEM,
|
||||
DER,
|
||||
}
|
||||
|
||||
/// Builder structure for an HTTP request.
|
||||
|
|
@ -145,7 +157,7 @@ pub struct Response<T> {
|
|||
pub body: T,
|
||||
}
|
||||
|
||||
impl <'a> Request<'a> {
|
||||
impl<'a> Request<'a> {
|
||||
/// Initiate an HTTP request with the given method and URL.
|
||||
fn new(method: Method, url: &'a str) -> Self {
|
||||
Request {
|
||||
|
|
@ -158,19 +170,29 @@ impl <'a> Request<'a> {
|
|||
}
|
||||
|
||||
/// Initiate a GET request with the given URL.
|
||||
pub fn get(url: &'a str) -> Self { Request::new(Method::Get, url) }
|
||||
pub fn get(url: &'a str) -> Self {
|
||||
Request::new(Method::Get, url)
|
||||
}
|
||||
|
||||
/// Initiate a POST request with the given URL.
|
||||
pub fn post(url: &'a str) -> Self { Request::new(Method::Post, url) }
|
||||
pub fn post(url: &'a str) -> Self {
|
||||
Request::new(Method::Post, url)
|
||||
}
|
||||
|
||||
/// Initiate a PUT request with the given URL.
|
||||
pub fn put(url: &'a str) -> Self { Request::new(Method::Put, url) }
|
||||
pub fn put(url: &'a str) -> Self {
|
||||
Request::new(Method::Put, url)
|
||||
}
|
||||
|
||||
/// Initiate a PATCH request with the given URL.
|
||||
pub fn patch(url: &'a str) -> Self { Request::new(Method::Patch, url) }
|
||||
pub fn patch(url: &'a str) -> Self {
|
||||
Request::new(Method::Patch, url)
|
||||
}
|
||||
|
||||
/// Initiate a DELETE request with the given URL.
|
||||
pub fn delete(url: &'a str) -> Self { Request::new(Method::Delete, url) }
|
||||
pub fn delete(url: &'a str) -> Self {
|
||||
Request::new(Method::Delete, url)
|
||||
}
|
||||
|
||||
/// Add an HTTP header to a request.
|
||||
pub fn header(mut self, k: &str, v: &str) -> Result<Self, curl::Error> {
|
||||
|
|
@ -188,7 +210,8 @@ impl <'a> Request<'a> {
|
|||
/// Set the `Authorization` header to a `Bearer` value with the
|
||||
/// supplied token.
|
||||
pub fn bearer_auth(mut self, token: &str) -> Result<Self, curl::Error> {
|
||||
self.headers.append(&format!("Authorization: Bearer {}", token))?;
|
||||
self.headers
|
||||
.append(&format!("Authorization: Bearer {}", token))?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
|
|
@ -212,8 +235,11 @@ impl <'a> Request<'a> {
|
|||
/// Consult the documentation for the `ssl_cert` and `ssl_key`
|
||||
/// functions in `curl::easy::Easy2` for details on supported
|
||||
/// formats and defaults.
|
||||
pub fn tls_client_cert<P: AsRef<Path>>(mut self, cert_type: CertType, cert: P)
|
||||
-> Result<Self, curl::Error> {
|
||||
pub fn tls_client_cert<P: AsRef<Path>>(
|
||||
mut self,
|
||||
cert_type: CertType,
|
||||
cert: P,
|
||||
) -> Result<Self, curl::Error> {
|
||||
self.handle.ssl_cert(cert)?;
|
||||
self.handle.ssl_cert_type(match cert_type {
|
||||
CertType::P12 => "P12",
|
||||
|
|
@ -262,13 +288,17 @@ impl <'a> Request<'a> {
|
|||
/// ```
|
||||
/// # use crimp::Request;
|
||||
/// let response = Request::get("https://httpbin.org/get")
|
||||
/// .with_handle(|mut handle| handle.referer("Example-Referer")).unwrap()
|
||||
/// .send().unwrap();
|
||||
/// .with_handle(|mut handle| handle.referer("Example-Referer"))
|
||||
/// .unwrap()
|
||||
/// .send()
|
||||
/// .unwrap();
|
||||
/// #
|
||||
/// # assert!(response.is_success());
|
||||
/// ```
|
||||
pub fn with_handle<F>(mut self, function: F) -> Result<Self, curl::Error>
|
||||
where F: FnOnce(&mut Easy) -> Result<(), curl::Error> {
|
||||
where
|
||||
F: FnOnce(&mut Easy) -> Result<(), curl::Error>,
|
||||
{
|
||||
function(&mut self.handle)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
|
@ -293,12 +323,15 @@ impl <'a> Request<'a> {
|
|||
/// let mut form = Form::new();
|
||||
/// form.part("some-name")
|
||||
/// .contents("some-data".as_bytes())
|
||||
/// .add().unwrap();
|
||||
/// .add()
|
||||
/// .unwrap();
|
||||
///
|
||||
/// let response = Request::post("https://httpbin.org/post")
|
||||
/// .user_agent("crimp test suite").unwrap()
|
||||
/// .user_agent("crimp test suite")
|
||||
/// .unwrap()
|
||||
/// .form(form)
|
||||
/// .send().unwrap();
|
||||
/// .send()
|
||||
/// .unwrap();
|
||||
/// #
|
||||
/// # assert_eq!(200, response.status, "form POST should succeed");
|
||||
/// # assert_eq!(
|
||||
|
|
@ -330,10 +363,10 @@ impl <'a> Request<'a> {
|
|||
self.handle.url(self.url)?;
|
||||
|
||||
match self.method {
|
||||
Method::Get => self.handle.get(true)?,
|
||||
Method::Post => self.handle.post(true)?,
|
||||
Method::Put => self.handle.put(true)?,
|
||||
Method::Patch => self.handle.custom_request("PATCH")?,
|
||||
Method::Get => self.handle.get(true)?,
|
||||
Method::Post => self.handle.post(true)?,
|
||||
Method::Put => self.handle.put(true)?,
|
||||
Method::Patch => self.handle.custom_request("PATCH")?,
|
||||
Method::Delete => self.handle.custom_request("DELETE")?,
|
||||
}
|
||||
|
||||
|
|
@ -351,21 +384,22 @@ impl <'a> Request<'a> {
|
|||
|
||||
// Optionally set content type if a body payload is configured
|
||||
// and configure the expected body size (or form payload).
|
||||
match self.body {
|
||||
match self.body {
|
||||
Body::Bytes { content_type, data } => {
|
||||
self.handle.post_field_size(data.len() as u64)?;
|
||||
self.headers.append(&format!("Content-Type: {}", content_type))?;
|
||||
},
|
||||
self.headers
|
||||
.append(&format!("Content-Type: {}", content_type))?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
Body::Json(ref data) => {
|
||||
self.handle.post_field_size(data.len() as u64)?;
|
||||
self.headers.append("Content-Type: application/json")?;
|
||||
},
|
||||
}
|
||||
|
||||
// Do not set content-type header at all if there is no
|
||||
// body, or if the form handler was invoked above.
|
||||
_ => (),
|
||||
// Do not set content-type header at all if there is no
|
||||
// body, or if the form handler was invoked above.
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// Configure headers on the request:
|
||||
|
|
@ -407,9 +441,7 @@ impl <'a> Request<'a> {
|
|||
return true;
|
||||
}
|
||||
|
||||
headers.insert(
|
||||
split[0].trim().to_string(), split[1].trim().to_string()
|
||||
);
|
||||
headers.insert(split[0].trim().to_string(), split[1].trim().to_string());
|
||||
true
|
||||
})?;
|
||||
|
||||
|
|
@ -427,7 +459,7 @@ impl <'a> Request<'a> {
|
|||
Ok(Response {
|
||||
status: self.handle.response_code()?,
|
||||
headers,
|
||||
body
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -438,13 +470,14 @@ impl <'a> Request<'a> {
|
|||
///
|
||||
/// As we manually set the expected upload size, cURL will call the
|
||||
/// read callback repeatedly until it has all the data it needs.
|
||||
fn chunked_read_function<'easy, 'data>(transfer: &mut Transfer<'easy, 'data>,
|
||||
data: &'data [u8]) -> Result<(), curl::Error> {
|
||||
fn chunked_read_function<'easy, 'data>(
|
||||
transfer: &mut Transfer<'easy, 'data>,
|
||||
data: &'data [u8],
|
||||
) -> Result<(), curl::Error> {
|
||||
let mut data = data;
|
||||
|
||||
transfer.read_function(move |mut into| {
|
||||
let written = into.write(data)
|
||||
.map_err(|_| ReadError::Abort)?;
|
||||
let written = into.write(data).map_err(|_| ReadError::Abort)?;
|
||||
|
||||
data = &data[written..];
|
||||
|
||||
|
|
@ -452,7 +485,7 @@ fn chunked_read_function<'easy, 'data>(transfer: &mut Transfer<'easy, 'data>,
|
|||
})
|
||||
}
|
||||
|
||||
impl <T> Response<T> {
|
||||
impl<T> Response<T> {
|
||||
/// Check whether the status code of this HTTP response is a
|
||||
/// success (i.e. in the 200-299 range).
|
||||
pub fn is_success(&self) -> bool {
|
||||
|
|
@ -466,9 +499,11 @@ impl <T> Response<T> {
|
|||
/// This function exists for convenience to avoid having to write
|
||||
/// repetitive `if !response.is_success() { ... }` blocks.
|
||||
pub fn error_for_status<F, E>(self, closure: F) -> Result<Self, E>
|
||||
where F: FnOnce(Self) -> E {
|
||||
where
|
||||
F: FnOnce(Self) -> E,
|
||||
{
|
||||
if !self.is_success() {
|
||||
return Err(closure(self))
|
||||
return Err(closure(self));
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
// docker run --rm -p 4662:80 kennethreitz/httpbin
|
||||
|
||||
use super::*;
|
||||
use serde_json::{Value, json};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
// These tests check whether the correct HTTP method is used in the
|
||||
// requests.
|
||||
|
|
@ -14,7 +14,8 @@ use serde_json::{Value, json};
|
|||
#[test]
|
||||
fn test_http_get() {
|
||||
let resp = Request::get("http://127.0.0.1:4662/get")
|
||||
.send().expect("failed to send request");
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert!(resp.is_success(), "request should have succeeded");
|
||||
}
|
||||
|
|
@ -22,7 +23,8 @@ fn test_http_get() {
|
|||
#[test]
|
||||
fn test_http_delete() {
|
||||
let resp = Request::delete("http://127.0.0.1:4662/delete")
|
||||
.send().expect("failed to send request");
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||
}
|
||||
|
|
@ -30,7 +32,8 @@ fn test_http_delete() {
|
|||
#[test]
|
||||
fn test_http_put() {
|
||||
let resp = Request::put("http://127.0.0.1:4662/put")
|
||||
.send().expect("failed to send request");
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||
}
|
||||
|
|
@ -38,7 +41,8 @@ fn test_http_put() {
|
|||
#[test]
|
||||
fn test_http_patch() {
|
||||
let resp = Request::patch("http://127.0.0.1:4662/patch")
|
||||
.send().expect("failed to send request");
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||
}
|
||||
|
|
@ -50,18 +54,25 @@ fn test_http_patch() {
|
|||
fn test_http_post() {
|
||||
let body = "test body";
|
||||
let response = Request::post("http://127.0.0.1:4662/post")
|
||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
||||
.user_agent("crimp test suite")
|
||||
.expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5))
|
||||
.expect("failed to set request timeout")
|
||||
.body("text/plain", &body.as_bytes())
|
||||
.send().expect("failed to send request")
|
||||
.as_json::<Value>().expect("failed to deserialize response");
|
||||
.send()
|
||||
.expect("failed to send request")
|
||||
.as_json::<Value>()
|
||||
.expect("failed to deserialize response");
|
||||
|
||||
let data = response.body;
|
||||
|
||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||
|
||||
assert_eq!(data.get("data").unwrap(), &json!("test body"),
|
||||
"test body should have been POSTed");
|
||||
assert_eq!(
|
||||
data.get("data").unwrap(),
|
||||
&json!("test body"),
|
||||
"test body should have been POSTed"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
||||
|
|
@ -70,26 +81,34 @@ fn test_http_post() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "json")] #[test]
|
||||
#[cfg(feature = "json")]
|
||||
#[test]
|
||||
fn test_http_post_json() {
|
||||
let body = json!({
|
||||
"purpose": "testing!"
|
||||
});
|
||||
|
||||
let response = Request::post("http://127.0.0.1:4662/post")
|
||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
||||
.json(&body).expect("request serialization failed")
|
||||
.send().expect("failed to send request")
|
||||
.as_json::<Value>().expect("failed to deserialize response");
|
||||
|
||||
.user_agent("crimp test suite")
|
||||
.expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5))
|
||||
.expect("failed to set request timeout")
|
||||
.json(&body)
|
||||
.expect("request serialization failed")
|
||||
.send()
|
||||
.expect("failed to send request")
|
||||
.as_json::<Value>()
|
||||
.expect("failed to deserialize response");
|
||||
|
||||
let data = response.body;
|
||||
|
||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||
|
||||
assert_eq!(data.get("json").unwrap(), &body,
|
||||
"test body should have been POSTed");
|
||||
assert_eq!(
|
||||
data.get("json").unwrap(),
|
||||
&body,
|
||||
"test body should have been POSTed"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
||||
|
|
@ -104,8 +123,10 @@ fn test_http_post_json() {
|
|||
#[test]
|
||||
fn test_bearer_auth() {
|
||||
let response = Request::get("http://127.0.0.1:4662/bearer")
|
||||
.bearer_auth("some-token").expect("failed to set auth header")
|
||||
.send().expect("failed to send request");
|
||||
.bearer_auth("some-token")
|
||||
.expect("failed to set auth header")
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert!(response.is_success(), "authorized request should succeed");
|
||||
}
|
||||
|
|
@ -115,8 +136,10 @@ fn test_basic_auth() {
|
|||
let request = Request::get("http://127.0.0.1:4662/basic-auth/alan_watts/oneness");
|
||||
|
||||
let response = request
|
||||
.basic_auth("alan_watts", "oneness").expect("failed to set auth header")
|
||||
.send().expect("failed to send request");
|
||||
.basic_auth("alan_watts", "oneness")
|
||||
.expect("failed to set auth header")
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
assert!(response.is_success(), "authorized request should succeed");
|
||||
}
|
||||
|
|
@ -129,14 +152,20 @@ fn test_large_body() {
|
|||
|
||||
let resp = Request::post("http://127.0.0.1:4662/post")
|
||||
.body("application/octet-stream", &[0; BODY_SIZE])
|
||||
.send().expect("sending request")
|
||||
.as_json::<Value>().expect("JSON deserialisation");
|
||||
.send()
|
||||
.expect("sending request")
|
||||
.as_json::<Value>()
|
||||
.expect("JSON deserialisation");
|
||||
|
||||
// httpbin returns the uploaded data as a string in the `data`
|
||||
// field.
|
||||
let data = resp.body.get("data").unwrap().as_str().unwrap();
|
||||
|
||||
assert_eq!(BODY_SIZE, data.len(), "uploaded data length should be correct");
|
||||
assert_eq!(
|
||||
BODY_SIZE,
|
||||
data.len(),
|
||||
"uploaded data length should be correct"
|
||||
);
|
||||
}
|
||||
|
||||
// Tests for various other features.
|
||||
|
|
@ -144,9 +173,13 @@ fn test_large_body() {
|
|||
#[test]
|
||||
fn test_error_for_status() {
|
||||
let response = Request::get("http://127.0.0.1:4662/patch")
|
||||
.send().expect("failed to send request")
|
||||
.send()
|
||||
.expect("failed to send request")
|
||||
.error_for_status(|resp| format!("Response error code: {}", resp.status));
|
||||
|
||||
assert_eq!(Err("Response error code: 405".into()), response,
|
||||
"returned error should be converted into Result::Err");
|
||||
assert_eq!(
|
||||
Err("Response error code: 405".into()),
|
||||
response,
|
||||
"returned error should be converted into Result::Err"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue