Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make response body optional #75

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/ffi/easy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl Easy {

pub fn perform(&mut self,
body: Option<&mut Body>,
allow_null_body: bool,
progress: Option<Box<ProgressCb>>)
-> Result<Response, err::ErrCode> {
let mut builder = ResponseBuilder::new();
Expand Down Expand Up @@ -82,13 +83,14 @@ impl Easy {

// If the request failed, abort here
if !err.is_success() {
println!("err {}", err);
return Err(err);
}

// Try to get the response code
builder.code = try!(self.get_response_code());

Ok(builder.build())
Ok(builder.build(allow_null_body))
}

pub fn get_response_code(&self) -> Result<u32, err::ErrCode> {
Expand Down Expand Up @@ -138,18 +140,19 @@ impl Drop for Easy {
*
*/

#[derive(Debug)]
struct ResponseBuilder {
code: u32,
hdrs: HashMap<String,Vec<String>>,
body: Vec<u8>
body: Option<Vec<u8>>
}

impl ResponseBuilder {
fn new() -> ResponseBuilder {
ResponseBuilder {
code: 0,
hdrs: HashMap::new(),
body: Vec::new()
body: None
}
}

Expand All @@ -171,9 +174,9 @@ impl ResponseBuilder {
}
}

fn build(self) -> Response {
fn build(self, allow_null_body: bool) -> Response {
let ResponseBuilder { code, hdrs, body } = self;
Response::new(code, hdrs, body)
Response::new(code, hdrs, body, allow_null_body)
}
}

Expand Down Expand Up @@ -203,7 +206,17 @@ extern fn curl_write_fn(p: *mut u8, size: size_t, nmemb: size_t,
let builder: &mut ResponseBuilder = unsafe { mem::transmute(resp) };
let chunk = unsafe { slice::from_raw_parts(p as *const u8,
(size * nmemb) as usize) };
builder.body.extend(chunk.iter().map(|x| *x));
match builder.body {
Some(ref mut body) => {
body.extend(chunk.iter().map(|x| *x));
}
None => {
let mut new_body = Vec::new();
new_body.extend(chunk.iter().map(|x| *x));
builder.body = Some(new_body);
}
}

}

size * nmemb
Expand Down
8 changes: 6 additions & 2 deletions src/http/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ impl<'a, 'b> Request<'a, 'b> {
..
} = self;

let mut allow_null_body = false;
if follow {
try!(handle.easy.setopt(opt::FOLLOWLOCATION, 1));
}
Expand All @@ -302,7 +303,10 @@ impl<'a, 'b> Request<'a, 'b> {

match method {
Get => try!(handle.easy.setopt(opt::HTTPGET, 1)),
Head => try!(handle.easy.setopt(opt::NOBODY, 1)),
Head => {
allow_null_body = true;
try!(handle.easy.setopt(opt::NOBODY, 1));
}
Post => try!(handle.easy.setopt(opt::POST, 1)),
Put => try!(handle.easy.setopt(opt::UPLOAD, 1)),
Patch => {
Expand Down Expand Up @@ -377,7 +381,7 @@ impl<'a, 'b> Request<'a, 'b> {
try!(handle.easy.setopt(opt::HTTPHEADER, &ffi_headers));
}

handle.easy.perform(body.as_mut(), progress)
handle.easy.perform(body.as_mut(), allow_null_body, progress)
}
}

Expand Down
21 changes: 14 additions & 7 deletions src/http/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ use std::{fmt,str};
use std::collections::HashMap;

pub type Headers = HashMap<String, Vec<String>>;
pub type ResponseBody = Option<Vec<u8>>;

#[derive(Debug)]
pub struct Response {
code: u32,
hdrs: Headers,
body: Vec<u8>
body: ResponseBody
}

impl Response {
pub fn new(code: u32, hdrs: Headers, body: Vec<u8>) -> Response {
pub fn new(code: u32, hdrs: Headers, mut body: ResponseBody, allow_null_body: bool) -> Response {
if !allow_null_body && body.is_none(){
body = Some(Vec::new())
}
Response {
code: code,
hdrs: hdrs,
Expand All @@ -34,11 +38,11 @@ impl Response {
.unwrap_or(&[])
}

pub fn get_body<'a>(&'a self) -> &'a [u8] {
pub fn get_body<'a>(&'a self) -> &ResponseBody {
&self.body
}

pub fn move_body(self) -> Vec<u8> {
pub fn move_body(self) -> ResponseBody {
self.body
}
}
Expand All @@ -51,9 +55,12 @@ impl fmt::Display for Response {
try!(write!(fmt, "{}: {}, ", name, val.connect(", ")));
}

match str::from_utf8(&self.body) {
Ok(b) => try!(write!(fmt, "{}", b)),
Err(..) => try!(write!(fmt, "bytes[{}]", self.body.len()))
match self.body {
Some(ref body) => match str::from_utf8(&body) {
Ok(b) => try!(write!(fmt, "{}", b)),
Err(..) => try!(write!(fmt, "bytes[{}]", body.len()))
},
None => try!(write!(fmt, "NoBody")),
}

try!(write!(fmt, "]"));
Expand Down
4 changes: 2 additions & 2 deletions test/test_delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn test_delete_with_no_body() {
let res = res.unwrap();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -48,5 +48,5 @@ pub fn test_delete_binary_with_slice() {
let res = res.unwrap();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}
31 changes: 28 additions & 3 deletions test/test_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,36 @@ pub fn test_simple_get() {
srv.assert();

assert!(res.get_code() == 200, "code is {}", res.get_code());
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
assert!(res.get_headers().len() == 1);
assert!(res.get_header("content-length") == ["5".to_string()]);
}

#[test]
pub fn test_simple_get_with_empty_body() {
let srv = server!(
recv!(
b"GET / HTTP/1.1\r\n\
Host: localhost:{PORT}\r\n\
Accept: */*\r\n\r\n"), // Send the data
send!(
b"HTTP/1.1 200 OK\r\n\
Content-Length: 0\r\n\r\n\
\r\n")); // Sends

let res = handle()
.get(server::url("/"))
.exec().unwrap();

srv.assert();

println!("asdf:{:?}", res.get_body());
assert!(res.get_code() == 200, "code is {}", res.get_code());
assert!(res.get_body().clone().unwrap() == "".as_bytes());
assert!(res.get_headers().len() == 1);
assert!(res.get_header("content-length") == ["0".to_string()]);
}

#[test]
pub fn test_get_with_custom_headers() {
let srv = server!(
Expand All @@ -46,7 +71,7 @@ pub fn test_get_with_custom_headers() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
assert!(res.get_headers().len() == 1);
assert!(res.get_header("content-length") == ["5".to_string()]);
}
Expand Down Expand Up @@ -110,5 +135,5 @@ pub fn follows_redirects() {
srv2.assert();

assert!(res.get_code() == 200);
assert_eq!(res.get_body(), b"response!");
assert_eq!(res.get_body().clone().unwrap(), b"response!");
}
2 changes: 1 addition & 1 deletion test/test_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn test_simple_head() {
let res = res.unwrap();

assert!(res.get_code() == 200, "code is {}", res.get_code());
assert!(res.get_body() == []);
assert!(res.get_body().is_none());
assert!(res.get_headers().len() == 1);
assert!(res.get_header("content-length") == ["5".to_string()]);
}
14 changes: 7 additions & 7 deletions test/test_keep_alive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ pub fn test_get_requests() {
srv.assert();

assert!(res1.get_code() == 200);
assert!(res1.get_body() == "Hello".as_bytes());
assert!(res1.get_body().clone().unwrap() == "Hello".as_bytes());

assert!(res2.get_code() == 200);
assert!(res2.get_body() == "World".as_bytes());
assert!(res2.get_body().clone().unwrap() == "World".as_bytes());
}

#[test]
Expand All @@ -52,17 +52,17 @@ pub fn test_post_get_requests() {
NEXT\r\n\r\n")
);

let mut handle = handle().timeout(1000);
let mut handle = handle().timeout(5000);
let res1 = handle.post(server::url("/"), "Hello").exec().unwrap();
let res2 = handle.get(server::url("/next")).exec().unwrap();

srv.assert();

assert!(res1.get_code() == 200);
assert!(res1.get_body() == "World".as_bytes(), "actual={}",
String::from_utf8_lossy(res1.get_body()));
assert!(res1.get_body().clone().unwrap() == "World".as_bytes(), "actual={}",
String::from_utf8_lossy(&res1.get_body().clone().unwrap()));

assert!(res2.get_code() == 200);
assert!(res2.get_body() == "NEXT".as_bytes(), "actual={}",
String::from_utf8_lossy(res2.get_body()));
assert!(res2.get_body().clone().unwrap() == "NEXT".as_bytes(), "actual={}",
String::from_utf8_lossy(&res2.get_body().clone().unwrap()));
}
4 changes: 2 additions & 2 deletions test/test_patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn test_patch_binary_with_slice() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -49,5 +49,5 @@ pub fn test_patch_binary_with_content_type() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}
8 changes: 4 additions & 4 deletions test/test_post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn test_post_binary_with_slice() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -49,7 +49,7 @@ pub fn test_post_binary_with_string() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -76,7 +76,7 @@ pub fn test_post_binary_with_reader() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -103,5 +103,5 @@ pub fn test_post_binary_with_reader_and_content_length() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}
2 changes: 1 addition & 1 deletion test/test_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ pub fn test_proxy() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}
4 changes: 2 additions & 2 deletions test/test_put.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn test_put_binary_with_slice() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}

#[test]
Expand All @@ -49,5 +49,5 @@ pub fn test_put_binary_with_content_type() {
srv.assert();

assert!(res.get_code() == 200);
assert!(res.get_body() == "Hello".as_bytes());
assert!(res.get_body().clone().unwrap() == "Hello".as_bytes());
}