async_http_codec/internal/
dec_helpers.rs

1use crate::{RequestHead, ResponseHead};
2use http::header::HeaderName;
3use http::{HeaderMap, HeaderValue, Method, Request, Response, StatusCode, Uri, Version};
4use httparse::Header;
5use std::error::Error;
6use std::io;
7use std::io::ErrorKind::InvalidData;
8
9#[allow(deprecated)]
10pub fn request_head_parse(buffer: &[u8], max_headers: usize) -> io::Result<RequestHead<'static>> {
11    let mut headers = vec![httparse::EMPTY_HEADER; max_headers];
12    let mut parsed_request = httparse::Request::new(&mut headers);
13    if parsed_request
14        .parse(buffer)
15        .map_err(|err| io::Error::new(InvalidData, err.description()))?
16        .is_partial()
17    {
18        return Err(io::Error::new(InvalidData, "malformed HTTP head"));
19    }
20    if parsed_request.version != Some(1) {
21        return Err(io::Error::new(InvalidData, "unsupported HTTP version"));
22    }
23    let method = Method::from_bytes(parsed_request.method.unwrap_or("").as_bytes())
24        .map_err(|err| io::Error::new(InvalidData, err.description()))?;
25    let uri = parsed_request
26        .path
27        .unwrap_or("")
28        .parse::<Uri>()
29        .map_err(|_| io::Error::new(InvalidData, "invalid uri"))?;
30    let mut request = Request::new(());
31    *request.method_mut() = method;
32    *request.uri_mut() = uri;
33    *request.version_mut() = Version::HTTP_11;
34    let headers = request.headers_mut();
35    copy_parsed_headers(headers, parsed_request.headers)?;
36    Ok(RequestHead::from(request))
37}
38
39#[allow(deprecated)]
40pub fn response_head_parse(buffer: &[u8], max_headers: usize) -> io::Result<ResponseHead<'static>> {
41    let mut headers = vec![httparse::EMPTY_HEADER; max_headers];
42    let mut parsed_response = httparse::Response::new(&mut headers);
43    if parsed_response
44        .parse(buffer)
45        .map_err(|err| io::Error::new(InvalidData, err.description()))?
46        .is_partial()
47    {
48        return Err(io::Error::new(InvalidData, "malformed HTTP head"));
49    }
50    if parsed_response.version != Some(1) {
51        return Err(io::Error::new(InvalidData, "unsupported HTTP version"));
52    }
53    let mut response = Response::new(());
54    *response.version_mut() = Version::HTTP_11;
55    *response.status_mut() = StatusCode::from_u16(parsed_response.code.unwrap())
56        .map_err(|_| io::Error::new(InvalidData, "invalid status code"))?;
57    let headers = response.headers_mut();
58    copy_parsed_headers(headers, parsed_response.headers)?;
59    Ok(ResponseHead::from(response))
60}
61
62pub(crate) fn copy_parsed_headers(trg: &mut HeaderMap, parsed: &[Header]) -> io::Result<()> {
63    trg.reserve(parsed.len());
64    for header in parsed {
65        trg.append(
66            HeaderName::from_bytes(header.name.as_bytes())
67                .map_err(|_| io::Error::new(InvalidData, "invalid header name"))?,
68            HeaderValue::from_bytes(header.value)
69                .map_err(|_| io::Error::new(InvalidData, "invalid header value"))?,
70        );
71    }
72    Ok(())
73}