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