Struct rhymuweb::Response [−][src]
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 implementDisplay
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]
T: AsRef<[u8]>,
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
Error::StatusLineNotValidText
– the status line contained bytes which could not be decoded as valid UTF-8 textError::StatusLineNoProtocolDelimiter
– the protocol identifier part of the status line could not be parsed because no space character delimiting the protocol identifier from the numeric status code could be foundError::StatusLineProtocol
– the protocol identifier part of the status line is either missing or does not match “HTTP/1.1”Error::StatusLineNoStatusCodeDelimiter
– the numeric status code part of the status line could not be parsed because no space character delimiting the numeric status code from the reason phrase could be foundError::InvalidStatusCode
– the value of the numeric status code in the status line could not be parsedError::StatusCodeOutOfRange
– the value of the numeric status code in the status line is greater than 999, the maximum permitted valueError::Headers
– an error occurred parsing the response headersError::InvalidContentLength
– the value of the “Content-Length” header of the response could not be parsedError::ChunkSizeLineNotValidText
– a chunk size line contained bytes which could not be decoded as valid UTF-8 textError::InvalidChunkSize
– the value of a chunk size could not be parsedError::InvalidChunkTerminator
– extra junk was found at the end of a chunk rather than carriage-return and line-feed, which are requiredError::Trailer
– an error occurred parsing the headers contained in the trailer for the chunked-encoded body
Trait Implementations
Auto Trait Implementations
impl RefUnwindSafe for Response
impl Send for Response
impl Sync for Response
impl Unpin for Response
impl UnwindSafe for Response
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,