Skip to content

Instantly share code, notes, and snippets.

@alexpts
Created March 24, 2022 04:34
Show Gist options
  • Save alexpts/64e6d0d7c10771b7b758133ac44d4392 to your computer and use it in GitHub Desktop.
Save alexpts/64e6d0d7c10771b7b758133ac44d4392 to your computer and use it in GitHub Desktop.
rust-http-parser.rs
use std::collections::HashMap;
struct Message;
#[derive(Debug)]
struct Request<'a> {
body: &'a str,
method: &'a str,
uri: &'a str,
protocol: &'a str,
headers: HashMap<&'a str, Vec<&'a str>>
}
const HEADER_DELIMITER: &'static str = "\r\n";
const BODY_DELIMITER: &'static str = "\r\n\r\n";
impl Message {
pub fn parse_blocks(message: &str) -> (&str, &str, &str) {
let mut parts: Vec<&str> = message.split(BODY_DELIMITER).collect();
let body: &str = parts.pop().unwrap();
let (start_line, raw_headers) = parts[0].split_once("\r\n").unwrap();
(start_line, raw_headers, body)
}
pub fn parse_headers(headers: &str) -> HashMap<&str, Vec<&str>> {
let mut map: HashMap<&str, Vec<&str>> = HashMap::new();
for header_line in headers.split(HEADER_DELIMITER) {
let (name, value) = header_line.split_once(":").unwrap();
let header_values = map.entry(name)
.or_insert(Vec::with_capacity(1));
header_values.push(value.trim());
}
println!("!!!map: {:#?}", map);
map
}
pub fn parse_start_line_request(start_line: &str) -> (&str, &str, &str) {
let mut parts = start_line.split(" ");
let method = parts.next().unwrap();
let uri = parts.next().unwrap();
let protocol: &str = &parts.next().unwrap()[5..];
(method, uri, protocol)
}
}
fn main() {
let message_raw = "GET / HTTP/1.0\r\nconnection:keep-alive\r\nh1: v1 \r\nuser: 1\r\nuser:2\r\n\r\nHello";
let (start_line, raw_headers, body) = Message::parse_blocks(message_raw);
let headers= Message::parse_headers(raw_headers);
let (method, uri, protocol) = Message::parse_start_line_request(start_line);
let req = Request{
body,
headers,
method,
uri,
protocol
};
println!("req: {:#?}", req);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment