sark_core/http/codec/encode/
wire.rs1use o3::buffer::{Owned, Shared};
2
3use crate::http::Request;
4
5pub struct Wire;
6
7impl Wire {
8 pub fn dec_len(mut n: usize) -> usize {
9 if n == 0 {
10 return 1;
11 }
12 let mut digits = 0;
13 while n > 0 {
14 digits += 1;
15 n /= 10;
16 }
17 digits
18 }
19
20 pub fn write_dec(mut n: usize, buf: &mut [u8; 20]) -> usize {
21 if n == 0 {
22 buf[0] = b'0';
23 return 1;
24 }
25 let mut i = 20;
26 while n > 0 {
27 i -= 1;
28 buf[i] = b'0' + (n % 10) as u8;
29 n /= 10;
30 }
31 let len = 20 - i;
32 buf.copy_within(i..20, 0);
33 len
34 }
35
36 pub fn write_hex(n: usize, buf: &mut [u8; 16]) -> usize {
37 if n == 0 {
38 buf[0] = b'0';
39 return 1;
40 }
41 let mut i = 16;
42 let mut val = n;
43 while val > 0 {
44 i -= 1;
45 buf[i] = b"0123456789abcdef"[val & 0xf];
46 val >>= 4;
47 }
48 buf.copy_within(i..16, 0);
49 16 - i
50 }
51
52 pub fn chunk_prefix(size: usize) -> ([u8; 18], usize) {
53 let mut hex = [0u8; 16];
54 let hex_len = Self::write_hex(size, &mut hex);
55 let mut out = [0u8; 18];
56 out[..hex_len].copy_from_slice(&hex[..hex_len]);
57 out[hex_len] = b'\r';
58 out[hex_len + 1] = b'\n';
59 (out, hex_len + 2)
60 }
61
62 pub fn chunk_frame(body: Shared) -> Shared {
63 let (prefix, prefix_len) = Self::chunk_prefix(body.len());
64 let mut framed = Owned::with_capacity(prefix_len + body.len() + 2);
65 framed.extend_from_slice(&prefix[..prefix_len]);
66 framed.extend_from_slice(&body);
67 framed.extend_from_slice(b"\r\n");
68 framed.freeze()
69 }
70
71 pub fn request(req: &Request) -> Vec<u8> {
72 let mut buf = Vec::with_capacity(Self::estimate_request_capacity(req));
73 Self::write_request_head(&mut buf, req);
74
75 let body = req.body();
76 if !body.is_empty() && !req.headers().contains_key("content-length") {
77 let mut dec = [0u8; 20];
78 let dec_len = Self::write_dec(body.len(), &mut dec);
79 buf.extend_from_slice(b"Content-Length: ");
80 buf.extend_from_slice(&dec[..dec_len]);
81 buf.extend_from_slice(b"\r\n");
82 }
83
84 buf.extend_from_slice(b"\r\n");
85
86 if !body.is_empty() {
87 buf.extend_from_slice(body.as_ref());
88 }
89
90 buf
91 }
92
93 pub fn request_head(req: &Request) -> Vec<u8> {
94 let mut buf = Vec::with_capacity(
95 Self::estimate_request_capacity(req).saturating_sub(req.body().len()),
96 );
97 Self::write_request_head(&mut buf, req);
98 buf.extend_from_slice(b"\r\n");
99 buf
100 }
101
102 fn header_map_len(headers: &http::HeaderMap) -> usize {
103 headers
104 .iter()
105 .map(|(name, value)| name.as_str().len() + 2 + value.as_bytes().len() + 2)
106 .sum()
107 }
108
109 fn request_path(req: &Request) -> &str {
110 req.uri()
111 .path_and_query()
112 .map(|pq| pq.as_str())
113 .unwrap_or("/")
114 }
115
116 fn host_value(req: &Request) -> Option<&str> {
117 if req.headers().contains_key("host") {
118 return None;
119 }
120 let authority = req.uri().authority()?;
121 let scheme = req.uri().scheme_str().unwrap_or("http");
122 let default_port = if scheme == "https" { 443 } else { 80 };
123 if req.uri().port_u16() == Some(default_port) {
124 Some(authority.host())
125 } else {
126 Some(authority.as_str())
127 }
128 }
129
130 fn estimate_request_capacity(req: &Request) -> usize {
131 let mut cap = req.method().as_str().len()
132 + 1
133 + Self::request_path(req).len()
134 + b" HTTP/1.1\r\n".len();
135 cap += Self::header_map_len(req.headers());
136
137 if let Some(host) = Self::host_value(req) {
138 cap += b"Host: ".len() + host.len() + 2;
139 }
140
141 if !req.headers().contains_key("user-agent") {
142 cap += b"User-Agent: sark/0.1\r\n".len();
143 }
144 if !req.headers().contains_key("accept-encoding") {
145 cap += b"Accept-Encoding: gzip\r\n".len();
146 }
147
148 let body = req.body();
149 if !body.is_empty() && !req.headers().contains_key("content-length") {
150 cap += b"Content-Length: ".len() + Self::dec_len(body.len()) + 2;
151 }
152
153 cap + 2 + body.len()
154 }
155
156 fn write_request_head(buf: &mut Vec<u8>, req: &Request) {
157 buf.extend_from_slice(req.method().as_str().as_bytes());
158 buf.push(b' ');
159 buf.extend_from_slice(Self::request_path(req).as_bytes());
160 buf.extend_from_slice(b" HTTP/1.1\r\n");
161
162 if let Some(host) = Self::host_value(req) {
163 buf.extend_from_slice(b"Host: ");
164 buf.extend_from_slice(host.as_bytes());
165 buf.extend_from_slice(b"\r\n");
166 }
167
168 if !req.headers().contains_key("user-agent") {
169 buf.extend_from_slice(b"User-Agent: sark/0.1\r\n");
170 }
171
172 if !req.headers().contains_key("accept-encoding") {
173 buf.extend_from_slice(b"Accept-Encoding: gzip\r\n");
174 }
175
176 for (name, value) in req.headers().iter() {
177 buf.extend_from_slice(name.as_str().as_bytes());
178 buf.extend_from_slice(b": ");
179 buf.extend_from_slice(value.as_bytes());
180 buf.extend_from_slice(b"\r\n");
181 }
182 }
183}