Struct slinger::Response

source ·
pub struct Response { /* private fields */ }
Expand description

A Response to a submitted Request.

Implementations§

source§

impl Response

source

pub fn builder() -> Builder

An HTTP response builder

This type can be used to construct an instance of Response through a builder-like pattern.

source§

impl Response

source

pub fn text(&self) -> Result<String>

Get the response text.

This method decodes the response body with BOM sniffing and with malformed sequences replaced with the REPLACEMENT CHARACTER. Encoding is determined from the charset parameter of Content-Type header, and defaults to utf-8 if not presented.

§Note

If the charset feature is disabled the method will only attempt to decode the response as UTF-8, regardless of the given Content-Type

§Example
let content = slinger::get("http://httpbin.org/range/26")?.text()?;
Examples found in repository?
examples/proxy.rs (line 8)
4
5
6
7
8
9
10
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let proxy = slinger::Proxy::parse("http://127.0.0.1:8080").unwrap();
  let client = ClientBuilder::new().proxy(proxy).build().unwrap();
  let resp = client.get("https://httpbin.org/get").send()?;
  println!("{:?}", resp.text());
  Ok(())
}
More examples
Hide additional examples
examples/request_budiler.rs (line 11)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new().build().unwrap();
  let resp = client
    .post("https://httpbin.org/post")
    .header("XX", "XX")
    .header_line("X: X")
    .body(b"data".as_slice())
    .send()?;
  println!("{:?}", resp.text());
  let u = http::Uri::from_static("https://httpbin.org/post");
  let raw = Request::raw(u, "", true);
  println!("{:?}", raw);
  Ok(())
}
examples/smuggling.rs (line 32)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
fn cve_2020_11724() {
  let raw: &str = r#"GET /test1 HTTP/1.1
Host: 192.168.83.196:8081
Content-Length: 42
Transfer-Encoding: chunked

0

GET /test1 HTTP/1.1
Host: 192.168.83.196:8081
X: GET http://192.168.83.1:8080/admin.jsp HTTP/1.0

"#;
  // let proxy = slinger::Proxy::parse("http://127.0.0.1:8080").unwrap();
  let client = ClientBuilder::new().build().unwrap();
  // replace \n to \r\n
  let raw = raw.replace('\n', "\r\n");
  let resp = client
    .raw("http://127.0.0.1:9015/", raw, true)
    .send()
    .unwrap();
  println!("{:?}", resp.text());
  let command = resp.request().unwrap().get_command();
  println!("{}", command);
}

fn nginx() {
  let raw = r#"
GET /a HTTP/1.1
Host: localhost
Content-Length: 56

GET /_hidden/index.html HTTP/1.1
Host: notlocalhost


"#;
  let client = ClientBuilder::new().build().unwrap();
  // replace \n to \r\n
  let raw = raw.replace('\n', "\r\n");
  let resp = client
    .raw("http://127.0.0.1:9015/", raw, true)
    .send()
    .unwrap();
  println!("{:?}", resp.text());
  let command = resp.request().unwrap().get_command();
  println!("{}", command);
}
examples/base.rs (line 17)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new()
    .user_agent(HeaderValue::from_static(
      "Mozilla/5.0 (X11; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0",
    ))
    .build()
    .unwrap();
  let resp = slinger::get("http://httpbin.org/get")?;
  println!("{:?}", resp.body());
  let resp = client
    .post("http://httpbin.org/post")
    .body(b"test".to_vec())
    .send()?;
  println!("{:?}", resp.text());
  let req = Request::builder()
    .uri("http://httpbin.org/head")
    .method("HEAD")
    .header("pragma", "akamai-x-cache-on")
    .body(None)
    .unwrap();
  let resp = client.execute(req).unwrap();
  println!("{:?}", resp);
  Ok(())
}
source

pub fn status_code(&self) -> StatusCode

Get the StatusCode of this Response.

§Examples

Checking for general status class:

let resp = slinger::get("http://httpbin.org/get")?;
if resp.status().is_success() {
    println!("success!");
} else if resp.status().is_server_error() {
    println!("server error!");
} else {
    println!("Something else happened. Status: {:?}", resp.status());
}

Checking for specific status codes:

use slinger::Client;
use slinger::http::StatusCode;
let client = Client::new();

let resp = client.post("http://httpbin.org/post")
    .body("possibly too large")
    .send()?;

match resp.status_code() {
    StatusCode::OK => println!("success!"),
    StatusCode::PAYLOAD_TOO_LARGE => {
        println!("Request payload is too large!");
    }
    s => println!("Received response status: {s:?}"),
};
source

pub fn version(&self) -> Version

Get the HTTP Version of this Response.

source

pub fn headers(&self) -> &HeaderMap

Get the Headers of this Response.

§Example

Saving an etag when caching a file:

use slinger::Client;
use slinger::http::header::ETAG;

let client = Client::new();

let mut resp = client.get("http://httpbin.org/cache").send()?;
if resp.status_code().is_success() {
    if let Some(etag) = resp.headers().get(ETAG) {
        std::fs::write("etag", etag.as_bytes());
    }
}
source

pub fn headers_mut(&mut self) -> &mut HeaderMap

Get a mutable reference to the Headers of this Response.

source

pub fn content_length(&self) -> Option<u64>

Get the content-length of the response, if it is known.

Reasons it may not be known:

  • The server didn’t send a content-length header.
  • The response is gzipped and automatically decoded (thus changing the actual decoded length).
source

pub fn uri(&self) -> &Uri

Get the final http::Uri of this Response.

§Example
let resp = slinger::get("http://httpbin.org/redirect/1")?;
assert_eq!(resp.uri().to_string().as_str(), "http://httpbin.org/get");
source

pub fn body(&self) -> &Option<Body>

Get the full response body as Bytes.

§Example
let resp = slinger::get("http://httpbin.org/ip")?;
let body = resp.body();
println!("bytes: {body:?}");
Examples found in repository?
examples/base.rs (line 12)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new()
    .user_agent(HeaderValue::from_static(
      "Mozilla/5.0 (X11; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0",
    ))
    .build()
    .unwrap();
  let resp = slinger::get("http://httpbin.org/get")?;
  println!("{:?}", resp.body());
  let resp = client
    .post("http://httpbin.org/post")
    .body(b"test".to_vec())
    .send()?;
  println!("{:?}", resp.text());
  let req = Request::builder()
    .uri("http://httpbin.org/head")
    .method("HEAD")
    .header("pragma", "akamai-x-cache-on")
    .body(None)
    .unwrap();
  let resp = client.execute(req).unwrap();
  println!("{:?}", resp);
  Ok(())
}
source

pub fn body_mut(&mut self) -> &mut Option<Body>

private

source

pub fn extensions(&self) -> &Extensions

Returns a reference to the associated extensions.

Examples found in repository?
examples/redirect.rs (line 15)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn limit(max_redirect: usize) -> Result<(), Box<dyn std::error::Error>> {
  let redirect = slinger::redirect::Policy::Limit(max_redirect);
  let client = ClientBuilder::new().redirect(redirect).build().unwrap();
  let resp = client.get("http://httpbin.org/redirect/10").send()?;
  let record = resp.extensions().get::<Vec<HTTPRecord>>().unwrap();
  assert_eq!(record.len(), 3);
  Ok(())
}

fn jump() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new().build().unwrap();
  let resp = client
    .get("http://httpbin.org/redirect-to?url=http://www.example.com/")
    .send()?;
  let record = resp.extensions().get::<Vec<HTTPRecord>>().unwrap();
  println!("{:?}", record);
  assert_eq!(record.len(), 2);
  Ok(())
}

fn only_same_host() -> Result<(), Box<dyn std::error::Error>> {
  let redirect = slinger::redirect::Policy::Custom(slinger::redirect::only_same_host);
  let client = ClientBuilder::new().redirect(redirect).build().unwrap();
  let resp = client
    .get("http://httpbin.org/redirect-to?url=http://www.example.com/")
    .send()?;
  let record = resp.extensions().get::<Vec<HTTPRecord>>().unwrap();
  println!("{:?}", record);
  assert_eq!(record.len(), 1);
  let redirect_record = resp.redirect_record().unwrap();
  println!("{:?}", redirect_record);
  assert_eq!(
    redirect_record.next,
    Some(http::Uri::from_static("http://www.example.com/"))
  );
  Ok(())
}
source

pub fn extensions_mut(&mut self) -> &mut Extensions

Returns a mutable reference to the associated extensions.

source§

impl Response

放一些响应中间过程记录,存起来方便获取

source

pub fn local_peer_record(&self) -> Option<&LocalPeerRecord>

Get the remote address used to get this Response.

§Example
let resp = slinger::get("http://httpbin.org/redirect/1")?;
println!("httpbin.org address: {:?}", resp.local_peer_record());
source

pub fn http_record(&self) -> Option<&Vec<HTTPRecord>>

Get the http record used to get this Response.

§Example
let resp = slinger::get("http://httpbin.org/redirect/1")?;
println!("httpbin.org http: {:?}", resp.http_record());
Examples found in repository?
examples/http_record.rs (line 9)
3
4
5
6
7
8
9
10
11
12
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new().build().unwrap();
  let resp = client
    .get("https://httpbin.org/redirect-to?url=https%3A%2F%2Fhttpbin.org%2Fget")
    .send()?;
  println!("{:?}", resp.request());
  let record = resp.http_record().unwrap();
  println!("{:?}", record.len());
  Ok(())
}
source

pub fn request(&self) -> Option<&Request>

Get the request used to get this Response.

§Example
let resp = slinger::get("http://httpbin.org/redirect/1")?;
println!("httpbin.org request: {:?}", resp.request());
Examples found in repository?
examples/http_record.rs (line 8)
3
4
5
6
7
8
9
10
11
12
fn main() -> Result<(), Box<dyn std::error::Error>> {
  let client = ClientBuilder::new().build().unwrap();
  let resp = client
    .get("https://httpbin.org/redirect-to?url=https%3A%2F%2Fhttpbin.org%2Fget")
    .send()?;
  println!("{:?}", resp.request());
  let record = resp.http_record().unwrap();
  println!("{:?}", record.len());
  Ok(())
}
More examples
Hide additional examples
examples/smuggling.rs (line 33)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
fn cve_2020_11724() {
  let raw: &str = r#"GET /test1 HTTP/1.1
Host: 192.168.83.196:8081
Content-Length: 42
Transfer-Encoding: chunked

0

GET /test1 HTTP/1.1
Host: 192.168.83.196:8081
X: GET http://192.168.83.1:8080/admin.jsp HTTP/1.0

"#;
  // let proxy = slinger::Proxy::parse("http://127.0.0.1:8080").unwrap();
  let client = ClientBuilder::new().build().unwrap();
  // replace \n to \r\n
  let raw = raw.replace('\n', "\r\n");
  let resp = client
    .raw("http://127.0.0.1:9015/", raw, true)
    .send()
    .unwrap();
  println!("{:?}", resp.text());
  let command = resp.request().unwrap().get_command();
  println!("{}", command);
}

fn nginx() {
  let raw = r#"
GET /a HTTP/1.1
Host: localhost
Content-Length: 56

GET /_hidden/index.html HTTP/1.1
Host: notlocalhost


"#;
  let client = ClientBuilder::new().build().unwrap();
  // replace \n to \r\n
  let raw = raw.replace('\n', "\r\n");
  let resp = client
    .raw("http://127.0.0.1:9015/", raw, true)
    .send()
    .unwrap();
  println!("{:?}", resp.text());
  let command = resp.request().unwrap().get_command();
  println!("{}", command);
}
source

pub fn redirect_record(&self) -> Option<&RedirectRecord>

Get the redirect record used to get this Response.

§Example
let resp = slinger::get("http://httpbin.org/redirect-to?url=http://www.example.com/")?;
println!("httpbin.org redirect: {:?}", resp.redirect_record());
Examples found in repository?
examples/redirect.rs (line 40)
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn only_same_host() -> Result<(), Box<dyn std::error::Error>> {
  let redirect = slinger::redirect::Policy::Custom(slinger::redirect::only_same_host);
  let client = ClientBuilder::new().redirect(redirect).build().unwrap();
  let resp = client
    .get("http://httpbin.org/redirect-to?url=http://www.example.com/")
    .send()?;
  let record = resp.extensions().get::<Vec<HTTPRecord>>().unwrap();
  println!("{:?}", record);
  assert_eq!(record.len(), 1);
  let redirect_record = resp.redirect_record().unwrap();
  println!("{:?}", redirect_record);
  assert_eq!(
    redirect_record.next,
    Some(http::Uri::from_static("http://www.example.com/"))
  );
  Ok(())
}

Trait Implementations§

source§

impl Clone for Response

source§

fn clone(&self) -> Response

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Response

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Response

source§

fn default() -> Response

Returns the “default value” for a type. Read more
source§

impl<T> From<Response<T>> for Response
where T: Into<Body>,

source§

fn from(value: HttpResponse<T>) -> Self

Converts to this type from the input type.
source§

impl PartialEq for Response

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.