mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-12-23 11:02:43 +03:00
Merge pull request #15 from Orange-OpenSource/feature/add-http-response-version
Add http version in response
This commit is contained in:
commit
84586c9ec1
@ -48,7 +48,6 @@ pub struct ClientOptions {
|
|||||||
|
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Init HTTP hurl client
|
/// Init HTTP hurl client
|
||||||
///
|
///
|
||||||
@ -107,7 +106,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
easy::InfoType::HeaderIn => {
|
easy::InfoType::HeaderIn => {
|
||||||
eprint!("< {}", str::from_utf8(data).unwrap());
|
eprint!("< {}", str::from_utf8(data).unwrap());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -147,8 +146,11 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let status = self.handle.response_code().unwrap();
|
let status = self.handle.response_code().unwrap();
|
||||||
|
let first_line = lines.remove(0); // remove the status line
|
||||||
|
let version = self.parse_response_version(first_line)?;
|
||||||
let headers = self.parse_response_headers(&mut lines);
|
let headers = self.parse_response_headers(&mut lines);
|
||||||
|
|
||||||
|
|
||||||
if let Some(url) = self.get_follow_location(headers.clone()) {
|
if let Some(url) = self.get_follow_location(headers.clone()) {
|
||||||
let request = Request {
|
let request = Request {
|
||||||
method: Method::Get,
|
method: Method::Get,
|
||||||
@ -173,6 +175,7 @@ impl Client {
|
|||||||
self.redirect_count = redirect_count;
|
self.redirect_count = redirect_count;
|
||||||
|
|
||||||
Ok(Response {
|
Ok(Response {
|
||||||
|
version,
|
||||||
status,
|
status,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
@ -203,7 +206,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
fn set_method(&mut self, method: &Method) {
|
fn set_method(&mut self, method: &Method) {
|
||||||
match method {
|
match method {
|
||||||
Method::Get => self.handle.custom_request("GET").unwrap(),
|
Method::Get => self.handle.custom_request("GET").unwrap(),
|
||||||
Method::Post => self.handle.custom_request("POST").unwrap(),
|
Method::Post => self.handle.custom_request("POST").unwrap(),
|
||||||
Method::Put => self.handle.custom_request("PUT").unwrap(),
|
Method::Put => self.handle.custom_request("PUT").unwrap(),
|
||||||
Method::Head => self.handle.custom_request("HEAD").unwrap(),
|
Method::Head => self.handle.custom_request("HEAD").unwrap(),
|
||||||
@ -308,12 +311,27 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// parse response version
|
||||||
|
///
|
||||||
|
fn parse_response_version(&mut self, line: String) -> Result<Version, HttpError> {
|
||||||
|
if line.starts_with("HTTP/1.0") {
|
||||||
|
Ok(Version::Http10)
|
||||||
|
} else if line.starts_with("HTTP/1.1") {
|
||||||
|
Ok(Version::Http11)
|
||||||
|
} else if line.starts_with("HTTP/2") {
|
||||||
|
Ok(Version::Http2)
|
||||||
|
} else {
|
||||||
|
Err(HttpError::CouldNotParseResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// parse headers from libcurl responses
|
/// parse headers from libcurl responses
|
||||||
///
|
///
|
||||||
fn parse_response_headers(&mut self, lines: &mut Vec<String>) -> Vec<Header> {
|
fn parse_response_headers(&mut self, lines: &mut Vec<String>) -> Vec<Header> {
|
||||||
let mut headers: Vec<Header> = vec![];
|
let mut headers: Vec<Header> = vec![];
|
||||||
lines.remove(0); // remove the status line
|
|
||||||
lines.pop(); // remove the blank line between headers and body
|
lines.pop(); // remove the blank line between headers and body
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if let Some(header) = Header::parse(line.to_string()) {
|
if let Some(header) = Header::parse(line.to_string()) {
|
||||||
@ -398,7 +416,6 @@ impl Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Split an array of bytes into http lines (\r\n separator)
|
/// Split an array of bytes into http lines (\r\n separator)
|
||||||
///
|
///
|
||||||
@ -448,6 +465,5 @@ mod tests {
|
|||||||
assert_eq!(lines.get(0).unwrap().as_str(), "GET /hello HTTP/1.1");
|
assert_eq!(lines.get(0).unwrap().as_str(), "GET /hello HTTP/1.1");
|
||||||
assert_eq!(lines.get(1).unwrap().as_str(), "Host: localhost:8000");
|
assert_eq!(lines.get(1).unwrap().as_str(), "Host: localhost:8000");
|
||||||
assert_eq!(lines.get(2).unwrap().as_str(), "");
|
assert_eq!(lines.get(2).unwrap().as_str(), "");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,6 +32,7 @@ pub struct Request {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
|
pub version: Version,
|
||||||
pub status: u32,
|
pub status: u32,
|
||||||
pub headers: Vec<Header>,
|
pub headers: Vec<Header>,
|
||||||
pub body: Vec<u8>,
|
pub body: Vec<u8>,
|
||||||
@ -51,6 +52,13 @@ pub enum Method {
|
|||||||
Patch,
|
Patch,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Version {
|
||||||
|
Http10,
|
||||||
|
Http11,
|
||||||
|
Http2,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -96,12 +104,9 @@ pub struct Cookie {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl fmt::Display for RequestCookie {
|
impl fmt::Display for RequestCookie {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}={}", self.name, self.value)
|
write!(f, "{}={}", self.name, self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,22 +116,18 @@ pub enum HttpError {
|
|||||||
CouldNotResolveProxyName,
|
CouldNotResolveProxyName,
|
||||||
CouldNotResolveHost,
|
CouldNotResolveHost,
|
||||||
FailToConnect,
|
FailToConnect,
|
||||||
TooManyRedirect
|
TooManyRedirect,
|
||||||
|
CouldNotParseResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
|
|
||||||
///
|
///
|
||||||
/// return a list of headers values for the given header name
|
/// return a list of headers values for the given header name
|
||||||
///
|
///
|
||||||
pub fn get_header_values(&self, expected_name: String) -> Vec<String> {
|
pub fn get_header_values(&self, expected_name: String) -> Vec<String> {
|
||||||
self.headers
|
get_header_values(self.headers.clone(), expected_name)
|
||||||
.iter()
|
|
||||||
.filter_map(|Header{ name, value}| if name.clone() == expected_name { Some(value.to_string())} else { None })
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -136,27 +137,38 @@ impl Response {
|
|||||||
pub fn get_header_values(headers: Vec<Header>, expected_name: String) -> Vec<String> {
|
pub fn get_header_values(headers: Vec<Header>, expected_name: String) -> Vec<String> {
|
||||||
headers
|
headers
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|Header{ name, value}| if name.clone() == expected_name { Some(value.to_string())} else { None })
|
.filter_map(|Header { name, value }| if name.clone() == expected_name { Some(value.to_string()) } else { None })
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_header_values() {
|
fn get_header_values() {
|
||||||
let response = Response {
|
let response = Response {
|
||||||
|
version: Version::Http10,
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: vec![
|
headers: vec![
|
||||||
Header { name: "Content-Length".to_string(), value: "12".to_string() }
|
Header { name: "Content-Length".to_string(), value: "12".to_string() }
|
||||||
],
|
],
|
||||||
body: vec![]
|
body: vec![],
|
||||||
};
|
};
|
||||||
assert_eq!(response.get_header_values("Content-Length".to_string()), vec!["12".to_string()]);
|
assert_eq!(response.get_header_values("Content-Length".to_string()), vec!["12".to_string()]);
|
||||||
assert!(response.get_header_values("Unknown".to_string()).is_empty());
|
assert!(response.get_header_values("Unknown".to_string()).is_empty());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hello_http_request() -> Request {
|
||||||
|
Request {
|
||||||
|
method: Method::Get,
|
||||||
|
url: "http://localhost:8000/hello".to_string(),
|
||||||
|
querystring: vec![],
|
||||||
|
headers: vec![],
|
||||||
|
cookies: vec![],
|
||||||
|
body: vec![],
|
||||||
|
multipart: vec![],
|
||||||
|
form: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -88,6 +88,7 @@ fn test_hello() {
|
|||||||
let mut client = default_client();
|
let mut client = default_client();
|
||||||
let request = default_get_request("http://localhost:8000/hello".to_string());
|
let request = default_get_request("http://localhost:8000/hello".to_string());
|
||||||
let response = client.execute(&request, 0).unwrap();
|
let response = client.execute(&request, 0).unwrap();
|
||||||
|
assert_eq!(response.version, Version::Http10);
|
||||||
assert_eq!(response.status, 200);
|
assert_eq!(response.status, 200);
|
||||||
assert_eq!(response.body, b"Hello World!".to_vec());
|
assert_eq!(response.body, b"Hello World!".to_vec());
|
||||||
|
|
||||||
@ -95,7 +96,6 @@ fn test_hello() {
|
|||||||
assert!(response.headers.contains(&Header { name: "Content-Length".to_string(), value: "12".to_string() }));
|
assert!(response.headers.contains(&Header { name: "Content-Length".to_string(), value: "12".to_string() }));
|
||||||
assert!(response.headers.contains(&Header { name: "Content-Type".to_string(), value: "text/html; charset=utf-8".to_string() }));
|
assert!(response.headers.contains(&Header { name: "Content-Type".to_string(), value: "text/html; charset=utf-8".to_string() }));
|
||||||
assert_eq!(response.get_header_values("Date".to_string()).len(), 1);
|
assert_eq!(response.get_header_values("Date".to_string()).len(), 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
Loading…
Reference in New Issue
Block a user