<commit_before>use std::io::Error as IoError;
use std::io::{self, Cursor, ErrorKind, Read, Write};

use std::fmt;
use std::net::SocketAddr;
use std::str::FromStr;

use std::sync::mpsc::Sender;

use chunked_transfer::Decoder;
use util::EqualReader;
use {HTTPVersion, Header, Method, Response, StatusCode};

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
/// your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
/// worker threads.
///
/// # Pipelining
///
/// If a client sends multiple requests in a row (without waiting for the response), then you will
/// get multiple `Request` objects simultaneously. This is called *requests pipelining*.
/// Tiny-http automatically reorders the responses so that you don't need to worry about the order
/// in which you call `respond` or `into_writer`.
///
/// This mechanic is disabled if:
///
///  - The body of a request is large enough (handling requires pipelining requires storing the
///    body of the request in a buffer ; if the body is too big, tiny-http will avoid doing that)
///  - A request sends a `Expect: 100-continue` header (which means that the client waits to
///    know whether its body will be processed before sending it)
///  - A request sends a `Connection: close` header or `Connection: upgrade` header (used for
///    websockets), which indicates that this is the last request that will be received on this
///    connection
///
/// # Automatic cleanup
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
/// an empty response with a 500 status code (internal server error) will automatically be
/// sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
/// error" response will automatically be sent during the stack unwinding.
pub struct Request {
    // where to read the body from
    data_reader: Option<Box<dyn Read + Send + 'static>>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<dyn Write + Send + 'static>>,

    remote_addr: SocketAddr,

    // true if HTTPS, false if HTTP
    secure: bool,

    method: Method,

    path: String,

    http_version: HTTPVersion,

    headers: Vec<Header>,

    body_length: Option<usize>,

    // true if a `100 Continue` response must be sent when `as_reader()` is called
    must_send_continue: bool,

    // If Some, a message must be sent after responding
    notify_when_responded: Option<Sender<()>>,
}

/// A simpler version of a `Request` that is useful for testing. No data actually goes anywhere.
///
/// By default, `MockRequest` pretends to be an unsecure GET request for the server root (`/`)
/// with no headers. To create a `MockRequest` with different parameters, use the builder pattern:
///
/// ```
/// let request = MockRequest::new()
///     .with_method(Method::Post)
///     .with_path("/api/widgets")
///     .with_body("42");
/// ```
///
/// Then, convert the `MockRequest` into a real `Request` and pass it to the server under test:
///
/// ```
/// let response = server.handle_request(request.into());
/// assert_eq!(response.status_code(), StatusCode(200));
/// ```
pub struct MockRequest {
    body: &'static str,
    remote_addr: SocketAddr,
    // true if HTTPS, false if HTTP
    secure: bool,
    method: Method,
    path: &'static str,
    http_version: HTTPVersion,
    headers: Vec<Header>,
}

impl From<MockRequest> for Request {
    fn from(mock: MockRequest) -> Request {
        new_request(<commit_msg>Fix failing doctests<commit_after>use std::io::Error as IoError;
use std::io::{self, Cursor, ErrorKind, Read, Write};

use std::fmt;
use std::net::SocketAddr;
use std::str::FromStr;

use std::sync::mpsc::Sender;

use chunked_transfer::Decoder;
use util::EqualReader;
use {HTTPVersion, Header, Method, Response, StatusCode};

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
/// your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
/// worker threads.
///
/// # Pipelining
///
/// If a client sends multiple requests in a row (without waiting for the response), then you will
/// get multiple `Request` objects simultaneously. This is called *requests pipelining*.
/// Tiny-http automatically reorders the responses so that you don't need to worry about the order
/// in which you call `respond` or `into_writer`.
///
/// This mechanic is disabled if:
///
///  - The body of a request is large enough (handling requires pipelining requires storing the
///    body of the request in a buffer ; if the body is too big, tiny-http will avoid doing that)
///  - A request sends a `Expect: 100-continue` header (which means that the client waits to
///    know whether its body will be processed before sending it)
///  - A request sends a `Connection: close` header or `Connection: upgrade` header (used for
///    websockets), which indicates that this is the last request that will be received on this
///    connection
///
/// # Automatic cleanup
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
/// an empty response with a 500 status code (internal server error) will automatically be
/// sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
/// error" response will automatically be sent during the stack unwinding.
pub struct Request {
    // where to read the body from
    data_reader: Option<Box<dyn Read + Send + 'static>>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<dyn Write + Send + 'static>>,

    remote_addr: SocketAddr,

    // true if HTTPS, false if HTTP
    secure: bool,

    method: Method,

    path: String,

    http_version: HTTPVersion,

    headers: Vec<Header>,

    body_length: Option<usize>,

    // true if a `100 Continue` response must be sent when `as_reader()` is called
    must_send_continue: bool,

    // If Some, a message must be sent after responding
    notify_when_responded: Option<Sender<()>>,
}

/// A simpler version of a `Request` that is useful for testing. No data actually goes anywhere.
///
/// By default, `MockRequest` pretends to be an unsecure GET request for the server root (`/`)
/// with no headers. To create a `MockRequest` with different parameters, use the builder pattern:
///
/// ```
/// # use tiny_http::{Method, MockRequest};
/// let request = MockRequest::new()
///     .with_method(Method::Post)
///     .with_path("/api/widgets")
///     .with_body("42");
/// ```
///
/// Then, convert the `MockRequest` into a real `Request` and pass it to the server under test:
///
/// ```
/// # use tiny_http::{Method, MockRequest, Request, Response, Server, StatusCode};
/// # use std::io::Cursor;
/// # let request = MockRequest::new()
/// #     .with_method(Method::Post)
/// #     .with_path("/api/widgets")
/// #     .with_body("42");
/// # struct TestServer {
/// #     listener: Server,
/// # }
/// # let server = TestServer {
/// #     listener: Server::http("0.0.0.0:0").unwrap(),
/// # };
/// # impl TestServer {
/// #     fn handle_request(&self, request: Request) -> Response<Cursor<Vec<u8>>> {
/// #         Response::from_string("test")
/// #     }
/// # }
/// let response = server.handle_request(request.into());
/// assert_eq!(response.status_code(), StatusCode(200));
/// ```
pub struct MockRequest {
    body: &'static str,
    remote_addr: SocketAddr,
    // true if HTTPS, false if HTTP
    secure: bool,
    method: Method,
    path: &'static str,
    http_version: HTTPVersion,
    headers: Vec<Header>,
}

impl From<MockRequest> for Request {
    fn from(mock: MockRequest) -> Request {
        new_request(
{'fraction_non_alphanumeric': 0.13181305600801904, 'fraction_numerical': 0.004510712943240195, 'mean_word_length': 3.1464935064935067, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3547631', 'n_tokens_mistral': 2260, 'n_tokens_neox': 2200, 'n_words': 938}