Oct 28 2015

httparse v1.0

The HTTP/1.1 parser used in hyper, hasn’t really seen any API changes since it was designed, and in the spirit of moving “stable” things to 1.0, I bumped that magical number up.


If you mainly use hyper (or a framework on top, like iron, nickel, rustless, etc), then this really shouldn’t affect you at all. It’s just the parsing logic for the HTTP/1.1 spec in a standalone crate.

If you work on some other project that requires parsing HTTP11, then you may want to try using httparse. Why?

It’s fast.

First, some buzz words. It’s stateless. It’s zero-copy. It performs zero allocations. It’s design piggybacks on the design of picohttpparser, which does the same.

  • Stateless: Keeping state means branches. Branches slow down individual parsing attempts. Instead, state of a socket can and should be handled outside of the parser itself. As the socket receives more data, you can try to parse again
  • Zero-copy
  • Zero allocations

It’s safe.

To be fast, and yet safe, an Iterator is used to prevent unnecessary bounds checks. That implementation is encapsulated in an inner private module, so the safety is easier to audit, and a safe API is exposed from the module, so the main API must use the iterator safely.2

Coming 1.1 and 1.2

There’s two lower hanging fruit that could provide noticeable speed improvements: branch predictions, and SIMD. There’s an accepted Rust RFC for adding a likely intrinsic that gives us branch prediction, but its implementation needs an extra push to get in.

There’s the simd crate, with only 2 things preventing it from speeding up httparse: its using an unstable feature or three, and SSE4 support is needed to get _mm_cmpestri, which would provide the biggest boost.

Or maybe both of these will be available at the same time, and they both can be added in httparse 1.1.

Building your own HTTP library? Get out of here! <3 ↩︎

Don’t look at the next_8 API. It’s wonky. I wanted a safe way to get 8 bytes at a time, and also be able to safely tell the Iterator how far into those 8 bytes I actually got. It’d probably be better to make that a closure instead, like bytes.with_8(|eight| check!(eight))↩︎

  • #http
  • #hyper
  • #httparse
  • #rust
  • #rust-lang
  • #planet