1use http_wire::WireDecode;
9use http_wire::request::FullRequest;
10use http_wire::response::FullResponse;
11use std::mem::MaybeUninit;
12
13fn main() {
14 println!("=== HTTP Decoding Examples ===\n");
15
16 println!("1. Decoding a simple GET request:");
18 println!("-----------------------------------");
19 decode_simple_request();
20 println!();
21
22 println!("2. Decoding a POST request with body:");
24 println!("--------------------------------------");
25 decode_post_request();
26 println!();
27
28 println!("3. Decoding with uninitialized headers (optimized):");
30 println!("---------------------------------------------------");
31 decode_request_optimized();
32 println!();
33
34 println!("4. Decoding a chunked transfer-encoding request:");
36 println!("------------------------------------------------");
37 decode_chunked_request();
38 println!();
39
40 println!("5. Decoding HTTP responses:");
42 println!("---------------------------");
43 decode_responses();
44 println!();
45
46 println!("6. Handling incomplete messages:");
48 println!("--------------------------------");
49 handle_incomplete_messages();
50 println!();
51
52 println!("=== All examples completed successfully ===");
53}
54
55fn decode_simple_request() {
56 let raw = b"GET /api/users HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.68.0\r\n\r\n";
57
58 let mut headers = [httparse::EMPTY_HEADER; 16];
60
61 match FullRequest::decode(raw, &mut headers) {
62 Ok((request, total_len)) => {
63 println!("✓ Successfully decoded request");
64 println!(" Method: {}", request.head.method.unwrap());
65 println!(" Path: {}", request.head.path.unwrap());
66 println!(" Version: HTTP/1.{}", request.head.version.unwrap());
67 println!(" Headers:");
68 for header in request.head.headers {
69 println!(
70 " {}: {}",
71 header.name,
72 String::from_utf8_lossy(header.value)
73 );
74 }
75 println!(" Body length: {} bytes", request.body.len());
76 println!(" Total message length: {} bytes", total_len);
77 }
78 Err(e) => eprintln!("✗ Error: {:?}", e),
79 }
80}
81
82fn decode_post_request() {
83 let raw = b"POST /api/users HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\nContent-Length: 24\r\n\r\n{\"name\":\"John\",\"age\":30}";
84
85 let mut headers = [httparse::EMPTY_HEADER; 16];
86
87 match FullRequest::decode(raw, &mut headers) {
88 Ok((request, total_len)) => {
89 println!("✓ Successfully decoded POST request");
90 println!(" Method: {}", request.head.method.unwrap());
91 println!(" Path: {}", request.head.path.unwrap());
92 println!(" Headers:");
93 for header in request.head.headers {
94 println!(
95 " {}: {}",
96 header.name,
97 String::from_utf8_lossy(header.value)
98 );
99 }
100 println!(" Body: {}", String::from_utf8_lossy(request.body));
101 println!(" Total length: {} bytes", total_len);
102 }
103 Err(e) => eprintln!("✗ Error: {:?}", e),
104 }
105}
106
107fn decode_request_optimized() {
108 let raw =
109 b"GET /api/data HTTP/1.1\r\nHost: api.example.com\r\nAccept: application/json\r\n\r\n";
110
111 let mut headers = [const { MaybeUninit::uninit() }; 16];
114
115 match FullRequest::decode_uninit(raw, &mut headers) {
116 Ok((request, total_len)) => {
117 println!("✓ Successfully decoded with uninit headers (faster!)");
118 println!(" Method: {}", request.head.method.unwrap());
119 println!(" Path: {}", request.head.path.unwrap());
120 println!(" Headers count: {}", request.head.headers.len());
121 println!(" Total length: {} bytes", total_len);
122 println!();
123 println!(" Note: decode_uninit() is faster because it skips header");
124 println!(" initialization. Use this for performance-critical code.");
125 }
126 Err(e) => eprintln!("✗ Error: {:?}", e),
127 }
128}
129
130fn decode_chunked_request() {
131 let raw = b"POST /api/upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n6\r\n world\r\n0\r\n\r\n";
132
133 let mut headers = [httparse::EMPTY_HEADER; 16];
134
135 match FullRequest::decode(raw, &mut headers) {
136 Ok((request, total_len)) => {
137 println!("✓ Successfully decoded chunked request");
138 println!(" Method: {}", request.head.method.unwrap());
139 println!(" Transfer-Encoding: chunked");
140 println!(
141 " Raw body (with chunk markers): {} bytes",
142 request.body.len()
143 );
144 println!(" Total length (including chunks): {} bytes", total_len);
145 println!();
146 println!(" Note: request.body contains the raw chunked data including");
147 println!(" chunk size markers. Use a chunked decoder to extract");
148 println!(" the actual content if needed.");
149 }
150 Err(e) => eprintln!("✗ Error: {:?}", e),
151 }
152}
153
154fn decode_responses() {
155 let raw = b"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 15\r\n\r\n{\"status\":\"ok\"}";
157 let mut headers = [httparse::EMPTY_HEADER; 16];
158
159 match FullResponse::decode(raw, &mut headers) {
160 Ok((response, total_len)) => {
161 println!("✓ 200 OK Response:");
162 println!(" Status: {}", response.head.code.unwrap());
163 println!(" Reason: {}", response.head.reason.unwrap());
164 println!(" Body: {}", String::from_utf8_lossy(response.body));
165 println!(" Total length: {} bytes", total_len);
166 }
167 Err(e) => eprintln!("✗ Error: {:?}", e),
168 }
169
170 println!();
171
172 let raw = b"HTTP/1.1 404 Not Found\r\nContent-Length: 9\r\n\r\nNot Found";
174 let mut headers = [httparse::EMPTY_HEADER; 16];
175
176 match FullResponse::decode(raw, &mut headers) {
177 Ok((response, _)) => {
178 println!("✓ 404 Response:");
179 println!(" Status: {}", response.head.code.unwrap());
180 println!(" Reason: {}", response.head.reason.unwrap());
181 println!(" Body: {}", String::from_utf8_lossy(response.body));
182 }
183 Err(e) => eprintln!("✗ Error: {:?}", e),
184 }
185
186 println!();
187
188 let raw = b"HTTP/1.1 204 No Content\r\nServer: nginx\r\n\r\n";
190 let mut headers = [httparse::EMPTY_HEADER; 16];
191
192 match FullResponse::decode(raw, &mut headers) {
193 Ok((response, _)) => {
194 println!("✓ 204 No Content Response:");
195 println!(" Status: {}", response.head.code.unwrap());
196 println!(
197 " Body length: {} bytes (correct for 204)",
198 response.body.len()
199 );
200 }
201 Err(e) => eprintln!("✗ Error: {:?}", e),
202 }
203
204 println!();
205
206 println!(" Note: FullResponse does NOT support decode_uninit() because");
208 println!(" httparse::Response lacks parse_with_uninit_headers method.");
209 println!(" Attempting to use it will panic with a clear error message.");
210}
211
212fn handle_incomplete_messages() {
213 let raw = b"GET /api/test HTTP/1.1\r\nHost: example.com\r\n";
215 let mut headers = [httparse::EMPTY_HEADER; 16];
216
217 match FullRequest::decode(raw, &mut headers) {
218 Ok(_) => println!("✗ Should have failed!"),
219 Err(e) => println!("✓ Correctly detected incomplete headers: {:?}", e),
220 }
221
222 let raw = b"POST /api/test HTTP/1.1\r\nHost: example.com\r\nContent-Length: 100\r\n\r\nshort";
224 let mut headers = [httparse::EMPTY_HEADER; 16];
225
226 match FullRequest::decode(raw, &mut headers) {
227 Ok(_) => println!("✗ Should have failed!"),
228 Err(e) => println!("✓ Correctly detected incomplete body: {:?}", e),
229 }
230
231 println!();
232 println!(" These errors allow you to buffer more data and retry parsing");
233 println!(" when working with streaming sockets or incremental data.");
234}