Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

Commit

Permalink
⬆️ fixes for reqwest 0.9 (update on headers)
Browse files Browse the repository at this point in the history
  • Loading branch information
mockersf committed Sep 29, 2018
1 parent 3ec05cc commit 7b7325d
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 94 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ travis-ci = { repository = "mockersf/jenkins-api.rs" }

[dependencies]
reqwest = "0.9"
hyper = "0.11"

serde = "1.0"
serde_derive = "1.0"
Expand Down
12 changes: 1 addition & 11 deletions src/client_internals/builder.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::str::FromStr;

use failure::Error;
use reqwest::header::{Authorization, Basic, Headers};
use reqwest::{self, Client, Url};

use super::{Jenkins, User};
Expand Down Expand Up @@ -55,18 +54,9 @@ impl JenkinsBuilder {
Err(reqwest::UrlError::EmptyHost)?;
}

let mut headers = Headers::new();

if let Some(ref user) = self.user {
headers.set(Authorization(Basic {
username: user.username.clone(),
password: user.password.clone(),
}));
}

Ok(Jenkins {
url: self.url,
client: Client::builder().default_headers(headers).build()?,
client: Client::builder().build()?,
user: self.user,
csrf_enabled: self.csrf_enabled,
depth: self.depth,
Expand Down
72 changes: 12 additions & 60 deletions src/client_internals/csrf.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use failure;
use hyper;
use std::fmt;

use reqwest::header::{Formatter, Header, Raw};
use reqwest::RequestBuilder;
use reqwest::{header::HeaderName, header::HeaderValue, RequestBuilder};

use super::{errors, path::Path, Jenkins};
use super::{path::Path, Jenkins};

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
Expand All @@ -14,70 +11,25 @@ pub(crate) struct Crumb {
crumb_request_field: String,
}

impl Header for Crumb {
fn header_name() -> &'static str {
"Jenkins-Crumb"
}

fn parse_header(_: &Raw) -> Result<Self, hyper::error::Error> {
unimplemented!();
}

fn fmt_header(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.fmt_line(&self.crumb)
}
}

impl Jenkins {
pub(crate) fn add_csrf_to_request(
&self,
request_builder: &mut RequestBuilder,
) -> Result<(), failure::Error> {
request_builder: RequestBuilder,
) -> Result<RequestBuilder, failure::Error> {
if self.csrf_enabled {
let _ = request_builder.header(self.get_csrf()?);
let crumb = self.get_csrf()?;
debug!("{:?}", crumb);
Ok(request_builder.header(
HeaderName::from_lowercase(crumb.crumb_request_field.to_lowercase().as_bytes())?,
HeaderValue::from_str(&crumb.crumb)?,
))
} else {
Ok(request_builder)
}
Ok(())
}

pub(crate) fn get_csrf(&self) -> Result<Crumb, failure::Error> {
let crumb: Crumb = self.get(&Path::CrumbIssuer)?.json()?;
if crumb.crumb_request_field != Crumb::header_name() {
return Err(errors::Error::InvalidCrumbFieldName {
field_name: crumb.crumb_request_field,
}.into());
}
Ok(crumb)
}
}

#[cfg(test)]
mod tests {
extern crate mockito;

static JENKINS_URL: &'static str = mockito::SERVER_URL;

#[test]
fn get_invalid_crumb() {
let jenkins_client = ::JenkinsBuilder::new(JENKINS_URL).build().unwrap();

let _mock = mockito::mock("GET", "/crumbIssuer/api/json?depth=1")
.with_body(
r#"
{
"_class":"hudson.security.csrf.DefaultCrumbIssuer",
"crumb":"1234567890abcdef",
"crumbRequestField":"Invalid-Crumb"
}
"#,
).create();

let crumb = jenkins_client.get_csrf();

assert!(crumb.is_err());
assert_eq!(
format!("{:?}", crumb),
r#"Err(InvalidCrumbFieldName { field_name: "Invalid-Crumb" })"#
);
}

}
33 changes: 22 additions & 11 deletions src/client_internals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

use failure;
use regex::Regex;
use reqwest::header::ContentType;
use reqwest::{Body, Client, RequestBuilder, Response, StatusCode};
use reqwest::{
header::HeaderValue, header::CONTENT_TYPE, Body, Client, RequestBuilder, Response, StatusCode,
};
use serde::Serialize;
use std::fmt::Debug;
use std::string::ToString;
Expand Down Expand Up @@ -82,6 +83,10 @@ impl Jenkins {
}

fn send(&self, mut request_builder: RequestBuilder) -> Result<Response, failure::Error> {
if let Some(ref user) = self.user {
request_builder =
request_builder.basic_auth(user.username.clone(), user.password.clone());
}
let query = request_builder.build()?;
debug!("sending {} {}", query.method(), query.url());
Ok(self.client.execute(query)?)
Expand All @@ -104,17 +109,19 @@ impl Jenkins {
path: &Path,
qps: T,
) -> Result<Response, failure::Error> {
let mut query = self.client.get(&self.url_api_json(&path.to_string()));
let _ = query.query(&qps);
let query = self
.client
.get(&self.url_api_json(&path.to_string()))
.query(&qps);
Ok(Self::error_for_status(self.send(query)?)?)
}

pub(crate) fn post(&self, path: &Path) -> Result<Response, failure::Error> {
let mut request_builder = self.client.post(&self.url(&path.to_string()));

self.add_csrf_to_request(&mut request_builder)?;
request_builder = self.add_csrf_to_request(request_builder)?;

Ok(request_builder.send()?.error_for_status()?)
Ok(Self::error_for_status(self.send(request_builder)?)?)
}

pub(crate) fn post_with_body<T: Into<Body> + Debug>(
Expand All @@ -125,13 +132,17 @@ impl Jenkins {
) -> Result<Response, failure::Error> {
let mut request_builder = self.client.post(&self.url(&path.to_string()));

self.add_csrf_to_request(&mut request_builder)?;
request_builder = self.add_csrf_to_request(request_builder)?;

let _ = request_builder.header(ContentType::form_url_encoded());
let _ = request_builder.query(qps).body(body);
request_builder = request_builder.header(
CONTENT_TYPE,
HeaderValue::from_static("application/x-www-form-urlencoded"),
);
debug!("{:?}", body);
request_builder = request_builder.query(qps).body(body);
let mut response = self.send(request_builder)?;

if response.status() == StatusCode::InternalServerError {
if response.status() == StatusCode::INTERNAL_SERVER_ERROR {
let body = response.text()?;

let re = Regex::new(r"java.lang.([a-zA-Z]+): (.*)").unwrap();
Expand Down Expand Up @@ -279,7 +290,7 @@ mod tests {
assert_eq!(
format!("{:?}", response),
concat!(
r#"Err(Error { kind: ServerError(InternalServerError), "#,
r#"Err(Inner { kind: ServerError(500), "#,
r#"url: Some("http://127.0.0.1:1234/error-NewException?") })"#
)
);
Expand Down
7 changes: 3 additions & 4 deletions src/job/builder.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Helper to build a job

use failure::Error;

use reqwest::header::Location;
use reqwest::header::LOCATION;

use serde;
use serde_urlencoded;
Expand Down Expand Up @@ -117,9 +116,9 @@ impl<'a, 'b, 'c, 'd> JobBuilder<'a, 'b, 'c, 'd> {
)?
}
};
if let Some(location) = response.headers().get::<Location>() {
if let Some(location) = response.headers().get(LOCATION) {
Ok(ShortQueueItem {
url: location.lines().next().unwrap().to_string(),
url: location.to_str().unwrap().to_string(),
other_fields: None,
})
} else {
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
//! ```
//!

extern crate hyper;
extern crate reqwest;

#[macro_use]
Expand Down
13 changes: 7 additions & 6 deletions tests/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn should_be_forbidden() {
assert_eq!(
format!("{:?}", response),
format!(
"Err(Error {{ kind: ClientError(Unauthorized), url: Some(\"{}/api/json?depth=1\") }})",
"Err(Inner {{ kind: ClientError(401), url: Some(\"{}/api/json?depth=1\") }})",
JENKINS_URL
)
);
Expand Down Expand Up @@ -87,7 +87,7 @@ fn should_get_view_not_found() {
assert_eq!(
format!("{:?}", response),
format!(
"Err(Error {{ kind: ClientError(NotFound), url: Some(\"{}/view/zut/api/json?depth=1\") }})",
"Err(Inner {{ kind: ClientError(404), url: Some(\"{}/view/zut/api/json?depth=1\") }})",
JENKINS_URL
)
);
Expand Down Expand Up @@ -341,7 +341,7 @@ fn can_get_queue_item() {
.as_variant::<jenkins_api::job::FreeStyleProject>()
.unwrap()
.build(&jenkins);
assert!(triggered.is_ok());
assert_that!(triggered).named("job triggered").is_ok();

let triggered_ok = triggered.unwrap();

Expand Down Expand Up @@ -532,7 +532,7 @@ fn can_build_job_with_parameters() {
.with_parameters(&params)
.unwrap()
.send();
assert!(triggered.is_ok());
assert_that!(triggered).named("triggered job").is_ok();

let queue_item = triggered.unwrap().get_full_queue_item(&jenkins);
assert!(queue_item.is_ok());
Expand All @@ -543,13 +543,15 @@ fn can_build_job_with_parameters() {
let mut found_param2 = false;
let mut found_param3 = false;

// print!("{:?}", queue_item_ok);
for action in queue_item_ok.actions {
if let Ok(parameters) = action.as_variant::<jenkins_api::action::ParametersAction>() {
for param in parameters.parameters {
print!("{:#?}", param);
if let Ok(bool_param) =
param.as_variant::<jenkins_api::action::parameters::BooleanParameterValue>()
{
found_param1 = bool_param.value;
found_param1 = bool_param.value == params.bool_param;
}
if let Ok(string_param) =
param.as_variant::<jenkins_api::action::parameters::StringParameterValue>()
Expand All @@ -564,7 +566,6 @@ fn can_build_job_with_parameters() {
}
}
}

assert!(found_param1);
assert!(found_param2);
assert!(found_param3);
Expand Down

0 comments on commit 7b7325d

Please sign in to comment.