http4r_core/
client.rs

1use std::net::TcpStream;
2
3use crate::handler::Handler;
4use crate::headers::Headers;
5use crate::http_message;
6use crate::http_message::{HttpMessage, read_message_from_wire, Request, RequestOptions, Response, with_content_length, write_message_to_wire};
7use crate::http_message::Body::{BodyString};
8
9impl Client {
10    pub fn new(base_uri: &str, port: u16, options: Option<ClientOptions>) -> Client {
11        Client {
12            base_uri: base_uri.to_string(),
13            port,
14            options: options.unwrap_or(ClientOptions {
15                headers_size: 16384,
16                trailers_size: 16384,
17            }),
18            err: "".to_string()
19        }
20    }
21}
22
23impl Handler for Client {
24    fn handle<F>(self: &mut Client, req: Request, fun: F) -> ()
25        where F: FnOnce(Response) -> () + Sized {
26        let uri = format!("{}:{}", self.base_uri, self.port);
27        let mut stream = TcpStream::connect(uri.clone()).unwrap();
28
29        let with_host_header = req.with_header(("Host", uri.as_str()));
30        write_message_to_wire(&mut stream, HttpMessage::Request(with_host_header), RequestOptions::default());
31
32        let mut reader: &mut [u8] = &mut [0; 4096];
33        let mut chunks_writer = Vec::with_capacity(1048576);
34        let mut compress_writer = Vec::with_capacity(1048576);
35        let mut start_line_writer = Vec::with_capacity(16384);
36        let mut headers_writer = Vec::with_capacity(16384);
37        let mut trailers_writer = Vec::with_capacity(16384);
38
39        let result = read_message_from_wire(
40            stream.try_clone().unwrap(),
41            &mut reader,
42            &mut start_line_writer,
43            &mut headers_writer,
44            &mut chunks_writer,
45            &mut compress_writer,
46            &mut trailers_writer
47        );
48
49        let response = match result {
50            Ok(http_message::HttpMessage::Response(res)) => res,
51            Err(e) => {
52                self.err = e.to_string();
53                Response::bad_request(Headers::empty(), BodyString(self.err.as_str()))
54            },
55            _ => Response::bad_request(Headers::empty(), BodyString("will happen if server replies with invalid response"))
56        };
57
58        fun(response)
59    }
60}
61
62pub struct Client {
63    pub base_uri: String,
64    pub port: u16,
65    options: ClientOptions,
66    pub err: String,
67}
68
69pub struct ClientOptions {
70    headers_size: usize,
71    trailers_size: usize,
72}
73
74pub struct WithContentLength<H> where H: Handler {
75    next_handler: H,
76}
77
78impl<H> WithContentLength<H> where H: Handler {
79    pub fn new(next_handler: H) -> WithContentLength<H> {
80        WithContentLength {
81            next_handler
82        }
83    }
84}
85
86impl<H> Handler for WithContentLength<H> where H: Handler {
87    fn handle<F>(self: &mut WithContentLength<H>, req: Request, fun: F) -> ()
88        where F: FnOnce(Response) -> () + Sized {
89        let request = with_content_length(HttpMessage::Request(req)).to_req();
90        self.next_handler.handle(request, |res| {
91            fun(res)
92        })
93    }
94}