HTTP request/response parser written in Rust
Rust
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
src
.gitignore
.travis.yml
Cargo.toml
LICENSE
README.md

README.md

Bee HTTP Parser

Build Status

This is a parser for HTTP messages written in Rust. It parses both requests and responses, extracts the following information from HTTP message.

  • Request method
  • Request URL
  • Response status code
  • HTTP version
  • Header fields and values
  • Content-Length
  • Transfer-Encoding
  • Message body (Decodes chunked encoding)

This library is inspired by http-parser written in C. Thanks to the original authors.

Usage

extern crate bee;

use std::collections::HashMap;
use std::str::from_utf8;
use bee::http::{HttpMethod, HttpVersion};
use bee::http::parser::{Parser, ParseRequest, MessageHandler};

struct RequestHandler {
    version: Option<HttpVersion>,
    method: Option<HttpMethod>,
    url: Option<String>,
    headers: HashMap<String, String>,
    buffer: Vec<u8>,
}

impl MessageHandler for RequestHandler {
    fn on_method(&mut self, _: &Parser, method: HttpMethod) {
        self.method = Some(method);
    }

    fn on_url(&mut self, _: &Parser, length: uint) {
        self.url = match from_utf8(self.buffer.slice_to(length)) {
            Some(url) => Some(url.to_string()),
            None => None,
        };
        self.buffer.clear();
    }

    fn on_version(&mut self, _: &Parser, version: HttpVersion) {
        self.version = Some(version);
    }

    fn on_header_value(&mut self, _: &Parser, length: uint) {
        {
            let len = self.buffer.len();
            let name = {
                let slice = self.buffer.slice_to(len-length);
                match from_utf8(slice) {
                    Some(s) => s.clone(),
                    None => return,
                }
            };
            let value = {
                let slice = self.buffer.slice_from(len-length);
                match from_utf8(slice) {
                    Some(s) => s.clone(),
                    None => return,
                }
            };
            self.headers.insert(name.to_string(), value.to_string());
        }
        self.buffer.clear();
    }

    fn write(&mut self, _: &Parser, byte: &[u8]) {
        self.buffer.push_all(byte);
    }
}

fn main() {
    let data = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".as_bytes();
    let mut handler = RequestHandler {
        version: None,
        url: None,
        method: None,
        headers: HashMap::new(),
        buffer: Vec::new(),
    };
    let mut parser = Parser::new(ParseRequest);
    let parsed = parser.parse(data, &mut handler);
    println!("{} {} {}", handler.method, handler.url, handler.version);
}