Struct rhymuweb::Response[][src]

pub struct Response {
    pub body: Vec<u8>,
    pub headers: MessageHeaders,
    pub reason_phrase: Cow<'static, str>,
    pub status_code: usize,
    pub trailer: Vec<u8>,
    // some fields omitted
}

This type is used to parse and generate HTTP 1.1 responses.

Fields

body: Vec<u8>

This holds the bytes which compose the body of the response.

headers: MessageHeaders

This holds any headers for the response.

reason_phrase: Cow<'static, str>

This is the reason phrase in the response, which is a textual description associated with the numeric status code.

status_code: usize

This is the numeric status code in the response, which describes the result of the server’s attempt to understand and satisfy the client’s corresponding request. It is defined in IETF RFC 7231 section 6.

trailer: Vec<u8>

This holds any bytes received from the server that came after the HTTP response. They may be junk or the first bytes of the first message(s) sent by the server using a higher-level protocol. It’s not our business to judge. ¯_(ツ)_/¯

Implementations

impl Response[src]

pub fn generate(&self) -> Result<Vec<u8>, Error>[src]

Produce the raw bytes form of the response, according to the rules of IETF RFC 7320 section 3:

  • The status line appears first, containing the protocol identifier, numeric status code, and reason phrase.
  • The response header lines follow the status line.
  • An empty text line follows the header lines.
  • The body, if any, appears last. Its length is determined by the “Content-Length” header.

Examples

use rhymessage::Header;
use rhymuweb::Response;

let mut response = Response::new();
response.status_code = 200;
response.reason_phrase = "OK".into();
response.headers.add_header(Header{
    name: "Date".into(),
    value: "Mon, 27 Jul 2009 12:28:53 GMT".into()
});
response.headers.add_header(Header{
    name: "Accept-Ranges".into(),
    value: "bytes".into()
});
response.headers.add_header(Header{
    name: "Content-Type".into(),
    value: "text/plain".into()
});
response.body = "Hello World! My payload includes a trailing CRLF.\r\n".into();
response.headers.add_header(Header{
    name: "Content-Length".into(),
    value: format!("{}", response.body.len())
});
assert!(matches!(
    response.generate(),
    Ok(raw_response) if raw_response == format!(
        concat!(
            "HTTP/1.1 200 OK\r\n",
            "Date: Mon, 27 Jul 2009 12:28:53 GMT\r\n",
            "Accept-Ranges: bytes\r\n",
            "Content-Type: text/plain\r\n",
            "Content-Length: {}\r\n",
            "\r\n",
            "Hello World! My payload includes a trailing CRLF.\r\n",
        ),
        response.body.len()
    ).as_bytes()
));

Errors

  • Error::Headers – the headers generator is configured with a line limit constraint and one or more headers are too long and cannot be folded to fit within the constraint.
  • Error::StringFormat – while technically it shouldn’t happen, logically this may be returned if one of the internal string formatting functions should fail (which they shouldn’t unless something used internally doesn’t implement Display properly.

#[must_use]pub fn new() -> Self[src]

Create a new response value with default status code (200), reason phrase (“OK”), and no headers or body.

pub fn parse<T>(&mut self, raw_message: T) -> Result<ParseResults, Error> where
    T: AsRef<[u8]>, 
[src]

Feed more bytes into the parser, building the response internally, and detecting when the end of the response has been found.

This function may be called multiple times to parse input incrementally. Each call returns an indication of whether or not a message was parsed and how many input bytes were consumed.

Examples

use rhymuri::Uri;
use rhymuweb::{Response, ResponseParseResults, ResponseParseStatus};

let raw_response = concat!(
    "HTTP/1.1 200 OK\r\n",
    "Date: Mon, 27 Jul 2009 12:28:53 GMT\r\n",
    "Server: Apache\r\n",
    "Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT\r\n",
    "ETag: \"34aa387-d-1568eb00\"\r\n",
    "Accept-Ranges: bytes\r\n",
    "Transfer-Encoding: chunked\r\n",
    "Vary: Accept-Encoding\r\n",
    "Content-Type: text/plain\r\n",
    "Trailer: X-Foo\r\n",
    "\r\n",
    "C\r\n",
    "Hello World!\r\n",
    "16\r\n",
    " My payload includes a\r\n",
    "11\r\n",
    " trailing CRLF.\r\n\r\n",
    "0\r\n",
    "X-Foo: Bar\r\n",
    "\r\n",
);
let mut response = Response::new();
assert!(matches!(
    response.parse(raw_response),
    Ok(ResponseParseResults{
        status: ResponseParseStatus::Complete,
        consumed
    }) if consumed == raw_response.len()
));
assert_eq!(200, response.status_code);
assert_eq!("OK", response.reason_phrase);
assert!(response.headers.has_header("Date"));
assert_eq!(
    Some("Mon, 27 Jul 2009 12:28:53 GMT"),
    response.headers.header_value("Date").as_deref()
);
assert!(response.headers.has_header("Accept-Ranges"));
assert_eq!(
    Some("bytes"),
    response.headers.header_value("Accept-Ranges").as_deref()
);
assert!(response.headers.has_header("Content-Type"));
assert_eq!(
    Some("text/plain"),
    response.headers.header_value("Content-Type").as_deref()
);
assert_eq!(
    Some("Bar"),
    response.headers.header_value("X-Foo").as_deref()
);
assert_eq!(
    Some("51"),
    response.headers.header_value("Content-Length").as_deref()
);
assert_eq!(
    "Hello World! My payload includes a trailing CRLF.\r\n".as_bytes(),
    response.body
);
assert!(!response.headers.has_header_token("Transfer-Encoding", "chunked"));
assert!(!response.headers.has_header("Trailer"));
assert!(!response.headers.has_header("Transfer-Encoding"));
assert_eq!(
    "Hello World! My payload includes a trailing CRLF.\r\n".as_bytes(),
    response.body
);

Errors

Trait Implementations

impl Debug for Response[src]

impl Default for Response[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.