micro_http: some doc and code corrections
Signed-off-by: karthik nedunchezhiyan <karthik1705.n@gmail.com> Signed-off-by: YUAN LYU <lyuyuan92@gmail.com>
This commit is contained in:
committed by
Adrian Catangiu
parent
4ee7142098
commit
569230220f
@@ -21,25 +21,32 @@ pub enum Header {
|
||||
}
|
||||
|
||||
impl Header {
|
||||
/// Returns a byte slice representation of the object.
|
||||
pub fn raw(&self) -> &'static [u8] {
|
||||
match self {
|
||||
Header::ContentLength => b"Content-Length",
|
||||
Header::ContentType => b"Content-Type",
|
||||
Header::Expect => b"Expect",
|
||||
Header::TransferEncoding => b"Transfer-Encoding",
|
||||
Header::Server => b"Server",
|
||||
Self::ContentLength => b"Content-Length",
|
||||
Self::ContentType => b"Content-Type",
|
||||
Self::Expect => b"Expect",
|
||||
Self::TransferEncoding => b"Transfer-Encoding",
|
||||
Self::Server => b"Server",
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a byte slice into a Header structure. Header must be ASCII, so also
|
||||
/// UTF-8 valid.
|
||||
///
|
||||
/// # Errors
|
||||
/// `InvalidRequest` is returned if slice contains invalid utf8 characters.
|
||||
/// `InvalidHeader` is returned if unsupported header found.
|
||||
fn try_from(string: &[u8]) -> Result<Self, RequestError> {
|
||||
if let Ok(mut utf8_string) = String::from_utf8(string.to_vec()) {
|
||||
utf8_string.make_ascii_lowercase();
|
||||
match utf8_string.trim() {
|
||||
"content-length" => Ok(Header::ContentLength),
|
||||
"content-type" => Ok(Header::ContentType),
|
||||
"expect" => Ok(Header::Expect),
|
||||
"transfer-encoding" => Ok(Header::TransferEncoding),
|
||||
"server" => Ok(Header::Server),
|
||||
"content-length" => Ok(Self::ContentLength),
|
||||
"content-type" => Ok(Self::ContentType),
|
||||
"expect" => Ok(Self::Expect),
|
||||
"transfer-encoding" => Ok(Self::TransferEncoding),
|
||||
"server" => Ok(Self::Server),
|
||||
_ => Err(RequestError::InvalidHeader),
|
||||
}
|
||||
} else {
|
||||
@@ -75,16 +82,18 @@ pub struct Headers {
|
||||
chunked: bool,
|
||||
}
|
||||
|
||||
impl Headers {
|
||||
impl Default for Headers {
|
||||
/// By default Requests are created with no headers.
|
||||
pub fn default() -> Headers {
|
||||
Headers {
|
||||
content_length: 0,
|
||||
expect: false,
|
||||
chunked: false,
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
content_length: Default::default(),
|
||||
expect: Default::default(),
|
||||
chunked: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Headers {
|
||||
/// Expects one header line and parses it, updating the header structure or returning an
|
||||
/// error if the header is invalid.
|
||||
///
|
||||
@@ -94,6 +103,17 @@ impl Headers {
|
||||
/// `InvalidHeader` is returned when the parsed header is formatted incorrectly or suggests
|
||||
/// that the client is using HTTP features that we do not support in this implementation,
|
||||
/// which invalidates the request.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// extern crate micro_http;
|
||||
/// use micro_http::Headers;
|
||||
///
|
||||
/// let mut request_header = Headers::default();
|
||||
/// assert!(request_header.parse_header_line(b"Content-Length: 24").is_ok());
|
||||
/// assert!(request_header.parse_header_line(b"Content-Length: 24: 2").is_err());
|
||||
/// ```
|
||||
pub fn parse_header_line(&mut self, header_line: &[u8]) -> Result<(), RequestError> {
|
||||
// Headers must be ASCII, so also UTF-8 valid.
|
||||
match std::str::from_utf8(header_line) {
|
||||
@@ -104,17 +124,13 @@ impl Headers {
|
||||
}
|
||||
if let Ok(head) = Header::try_from(entry[0].as_bytes()) {
|
||||
match head {
|
||||
Header::ContentLength => {
|
||||
let try_numeric: Result<i32, std::num::ParseIntError> =
|
||||
std::str::FromStr::from_str(entry[1].trim());
|
||||
match try_numeric {
|
||||
Ok(content_length) if content_length >= 0 => {
|
||||
self.content_length = content_length;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(RequestError::InvalidHeader),
|
||||
Header::ContentLength => match entry[1].trim().parse::<i32>() {
|
||||
Ok(content_length) => {
|
||||
self.content_length = content_length;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Err(_) => Err(RequestError::InvalidHeader),
|
||||
},
|
||||
Header::ContentType => {
|
||||
match MediaType::try_from(entry[1].trim().as_bytes()) {
|
||||
Ok(_) => Ok(()),
|
||||
@@ -165,7 +181,7 @@ impl Headers {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn new(content_length: i32, expect: bool, chunked: bool) -> Self {
|
||||
Headers {
|
||||
Self {
|
||||
content_length,
|
||||
expect,
|
||||
chunked,
|
||||
@@ -196,7 +212,7 @@ impl Headers {
|
||||
pub fn try_from(bytes: &[u8]) -> Result<Headers, RequestError> {
|
||||
// Headers must be ASCII, so also UTF-8 valid.
|
||||
if let Ok(text) = std::str::from_utf8(bytes) {
|
||||
let mut headers = Headers::default();
|
||||
let mut headers = Self::default();
|
||||
|
||||
let header_lines = text.split("\r\n");
|
||||
for header_line in header_lines {
|
||||
@@ -224,30 +240,57 @@ pub enum MediaType {
|
||||
}
|
||||
|
||||
impl Default for MediaType {
|
||||
/// Default value for MediaType is application/json
|
||||
fn default() -> Self {
|
||||
MediaType::ApplicationJson
|
||||
Self::ApplicationJson
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaType {
|
||||
fn try_from(bytes: &[u8]) -> Result<Self, RequestError> {
|
||||
/// Parses a byte slice into a MediaType structure for a HTTP request. MediaType
|
||||
/// must be ASCII, so also UTF-8 valid.
|
||||
///
|
||||
/// # Errors
|
||||
/// The function returns `InvalidRequest` when parsing the byte stream fails or
|
||||
/// unsupported MediaType found.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// extern crate micro_http;
|
||||
/// use micro_http::MediaType;
|
||||
///
|
||||
/// assert!(MediaType::try_from(b"application/json").is_ok());
|
||||
/// assert!(MediaType::try_from(b"application/json2").is_err());
|
||||
/// ```
|
||||
pub fn try_from(bytes: &[u8]) -> Result<Self, RequestError> {
|
||||
if bytes.is_empty() {
|
||||
return Err(RequestError::InvalidRequest);
|
||||
}
|
||||
let utf8_slice =
|
||||
String::from_utf8(bytes.to_vec()).map_err(|_| RequestError::InvalidRequest)?;
|
||||
match utf8_slice.as_str().trim() {
|
||||
"text/plain" => Ok(MediaType::PlainText),
|
||||
"application/json" => Ok(MediaType::ApplicationJson),
|
||||
"text/plain" => Ok(Self::PlainText),
|
||||
"application/json" => Ok(Self::ApplicationJson),
|
||||
_ => Err(RequestError::InvalidRequest),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a static string representation of the object.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// extern crate micro_http;
|
||||
/// use micro_http::MediaType;
|
||||
///
|
||||
/// let media_type = MediaType::ApplicationJson;
|
||||
/// assert_eq!(media_type.as_str(), "application/json");
|
||||
/// ```
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
MediaType::PlainText => "text/plain",
|
||||
MediaType::ApplicationJson => "application/json",
|
||||
Self::PlainText => "text/plain",
|
||||
Self::ApplicationJson => "application/json",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@ pub enum RequestError {
|
||||
impl Display for RequestError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
match self {
|
||||
RequestError::InvalidHttpMethod(inner) => write!(f, "Invalid HTTP Method: {}", inner),
|
||||
RequestError::InvalidUri(inner) => write!(f, "Invalid URI: {}", inner),
|
||||
RequestError::InvalidHttpVersion(inner) => write!(f, "Invalid HTTP Version: {}", inner),
|
||||
RequestError::UnsupportedHeader => write!(f, "Unsupported header."),
|
||||
RequestError::InvalidHeader => write!(f, "Invalid header."),
|
||||
RequestError::InvalidRequest => write!(f, "Invalid request."),
|
||||
Self::InvalidHttpMethod(inner) => write!(f, "Invalid HTTP Method: {}", inner),
|
||||
Self::InvalidUri(inner) => write!(f, "Invalid URI: {}", inner),
|
||||
Self::InvalidHttpVersion(inner) => write!(f, "Invalid HTTP Version: {}", inner),
|
||||
Self::UnsupportedHeader => write!(f, "Unsupported header."),
|
||||
Self::InvalidHeader => write!(f, "Invalid header."),
|
||||
Self::InvalidRequest => write!(f, "Invalid request."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,10 +59,10 @@ pub enum ConnectionError {
|
||||
impl Display for ConnectionError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
match self {
|
||||
ConnectionError::ParseError(inner) => write!(f, "Parsing error: {}", inner),
|
||||
ConnectionError::StreamError(inner) => write!(f, "Stream error: {}", inner),
|
||||
ConnectionError::ConnectionClosed => write!(f, "Connection closed."),
|
||||
ConnectionError::InvalidWrite => write!(f, "Invalid write attempt."),
|
||||
Self::ParseError(inner) => write!(f, "Parsing error: {}", inner),
|
||||
Self::StreamError(inner) => write!(f, "Stream error: {}", inner),
|
||||
Self::ConnectionClosed => write!(f, "Connection closed."),
|
||||
Self::InvalidWrite => write!(f, "Invalid write attempt."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,9 +96,9 @@ pub enum ServerError {
|
||||
impl Display for ServerError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
match self {
|
||||
ServerError::IOError(inner) => write!(f, "IO error: {}", inner),
|
||||
ServerError::ConnectionError(inner) => write!(f, "Connection error: {}", inner),
|
||||
ServerError::ServerFull => write!(f, "Server is full."),
|
||||
Self::IOError(inner) => write!(f, "IO error: {}", inner),
|
||||
Self::ConnectionError(inner) => write!(f, "Connection error: {}", inner),
|
||||
Self::ServerFull => write!(f, "Server is full."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ pub struct Body {
|
||||
impl Body {
|
||||
/// Creates a new `Body` from a `String` input.
|
||||
pub fn new<T: Into<Vec<u8>>>(body: T) -> Self {
|
||||
Body { body: body.into() }
|
||||
Self { body: body.into() }
|
||||
}
|
||||
|
||||
/// Returns the body as an `u8 slice`.
|
||||
@@ -159,12 +159,12 @@ impl Method {
|
||||
/// an error, but when using the input b"GET", it returns Method::Get.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `RequestError` if the method specified by `bytes` is unsupported.
|
||||
/// `InvalidHttpMethod` is returned if the specified HTTP method is unsupported.
|
||||
pub fn try_from(bytes: &[u8]) -> Result<Self, RequestError> {
|
||||
match bytes {
|
||||
b"GET" => Ok(Method::Get),
|
||||
b"PUT" => Ok(Method::Put),
|
||||
b"PATCH" => Ok(Method::Patch),
|
||||
b"GET" => Ok(Self::Get),
|
||||
b"PUT" => Ok(Self::Put),
|
||||
b"PATCH" => Ok(Self::Patch),
|
||||
_ => Err(RequestError::InvalidHttpMethod("Unsupported HTTP method.")),
|
||||
}
|
||||
}
|
||||
@@ -172,9 +172,9 @@ impl Method {
|
||||
/// Returns an `u8 slice` corresponding to the Method.
|
||||
pub fn raw(self) -> &'static [u8] {
|
||||
match self {
|
||||
Method::Get => b"GET",
|
||||
Method::Put => b"PUT",
|
||||
Method::Patch => b"PATCH",
|
||||
Self::Get => b"GET",
|
||||
Self::Put => b"PUT",
|
||||
Self::Patch => b"PATCH",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,12 +208,19 @@ pub enum Version {
|
||||
Http11,
|
||||
}
|
||||
|
||||
impl Default for Version {
|
||||
/// Returns the default HTTP version = HTTP/1.1.
|
||||
fn default() -> Self {
|
||||
Self::Http11
|
||||
}
|
||||
}
|
||||
|
||||
impl Version {
|
||||
/// HTTP Version as an `u8 slice`.
|
||||
pub fn raw(self) -> &'static [u8] {
|
||||
match self {
|
||||
Version::Http10 => b"HTTP/1.0",
|
||||
Version::Http11 => b"HTTP/1.1",
|
||||
Self::Http10 => b"HTTP/1.0",
|
||||
Self::Http11 => b"HTTP/1.1",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,21 +230,16 @@ impl Version {
|
||||
/// The version is case sensitive and the accepted input is upper case.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns a `RequestError` when the version is not supported.
|
||||
/// Returns a `InvalidHttpVersion` when the HTTP version is not supported.
|
||||
pub fn try_from(bytes: &[u8]) -> Result<Self, RequestError> {
|
||||
match bytes {
|
||||
b"HTTP/1.0" => Ok(Version::Http10),
|
||||
b"HTTP/1.1" => Ok(Version::Http11),
|
||||
b"HTTP/1.0" => Ok(Self::Http10),
|
||||
b"HTTP/1.1" => Ok(Self::Http11),
|
||||
_ => Err(RequestError::InvalidHttpVersion(
|
||||
"Unsupported HTTP version.",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the default HTTP version = HTTP/1.1.
|
||||
pub fn default() -> Self {
|
||||
Version::Http11
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user