<story><title>Show HN: Micro HTTP server in 22 lines of C</title><url>https://twitter.com/ilyakurdyukov/status/1421349901720510465</url></story><parent_chain><item><author>jart</author><text>I&amp;#x27;m the author of the fastest open source HTTP server. Parsing HTTP 0.9, 1.0, and 1.1 is trivial. It&amp;#x27;s a walk in the park. It only takes about a hundred lines of code to create a proper O(n) parser. &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;jart&amp;#x2F;cosmopolitan&amp;#x2F;blob&amp;#x2F;0b317523a0875d83d650ce8a7b288e3b3500fbba&amp;#x2F;net&amp;#x2F;http&amp;#x2F;parsehttpmessage.c#L54&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;jart&amp;#x2F;cosmopolitan&amp;#x2F;blob&amp;#x2F;0b317523a0875d83d6...&lt;/a&gt;&lt;p&gt;The Joyent HTTP parser used by Node is very good but it&amp;#x27;s implemented in a way that makes the problem much more complicated than it needs to be. The biggest obstacle with high-performance HTTP message parsing is the case-insensitive string comparison of header field names. Some servers like thttpd do the naive thing and just use a long sequence of strcasecmp() statements. Joyent goes &amp;quot;fast&amp;quot; because it uses callbacks, which effectively punts the problem to the caller, and, for a few select headers which it handles itself, like Content-Length, it uses this really complicated internal &amp;quot;h_matching&amp;quot; thing for doing painstakingly written out hardcoded character compares. Redbean solves the problem by using better computer science: perfect hash tables. Thanks to gperf command. That makes the API itself much more elegant since the parser can not only go faster but return a hash-table like structure where individual headers can be indexed without performing string comparisons.</text></item><item><author>nly</author><text>No, parsing HTTP&amp;#x2F;1.x is a nightmare and definitely not simple. It wasn&amp;#x27;t even particularly well defined until 2014 when the original RFCs were modernized, and even now there are bugs reported in HTTP parsers all the time.&lt;p&gt;Node.js came out in 2009, a full ten years after HTTP&amp;#x2F;1.1 (RFC 2068) and its original http-parser is rather hard to follow, doesn&amp;#x27;t conform to the RFCs for performance reasons, and is considered unmaintainable by the author of it&amp;#x27;s replacement[0]&lt;p&gt;As for parsing HTML, well go look at how Cloudflare have stumbled[1]&lt;p&gt;[0] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;nodejs&amp;#x2F;llhttp&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;nodejs&amp;#x2F;llhttp&lt;/a&gt;&lt;p&gt;[1] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;blog.cloudflare.com&amp;#x2F;incident-report-on-memory-leak-caused-by-cloudflare-parser-bug&amp;#x2F;&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;blog.cloudflare.com&amp;#x2F;incident-report-on-memory-leak-c...&lt;/a&gt;</text></item><item><author>milansuk</author><text>That&amp;#x27;s the beauty of original HTTP - simplicity. Same as parsing HTML(in the 90s). With HTTPS(S as Secure) it&amp;#x27;s a whole different story and most programmers use some library.</text></item></parent_chain><comment><author>pornel</author><text>HTTP&amp;#x2F;1 is deceptive, because you think &amp;quot;oh, I&amp;#x27;ll just read RFC 2616, make a state machine, and I&amp;#x27;m done!&amp;quot;. But then writing a &lt;i&gt;browser-compatible&lt;/i&gt; HTTP&amp;#x2F;1 client is a whole another bag of problems that weren&amp;#x27;t even documented until recently.&lt;p&gt;For example, Content-Length isn&amp;#x27;t just a single header with an integer, like the spec says. You need to support responses with multiple Content-Length headers and comma-separated lists of potentially contradictory lengths, and then perform garbage error-recovery the way Internet Explorer or Chrome did. Getting this wrong will make your client hang, consume garbage, or allow response stuffing.&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;web-platform-tests&amp;#x2F;wpt&amp;#x2F;pull&amp;#x2F;10548&amp;#x2F;files&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;web-platform-tests&amp;#x2F;wpt&amp;#x2F;pull&amp;#x2F;10548&amp;#x2F;files&lt;/a&gt;&lt;p&gt;This problem does not exist in HTTP&amp;#x2F;2.</text></comment>
<story><title>Show HN: Micro HTTP server in 22 lines of C</title><url>https://twitter.com/ilyakurdyukov/status/1421349901720510465</url></story><parent_chain><item><author>jart</author><text>I&amp;#x27;m the author of the fastest open source HTTP server. Parsing HTTP 0.9, 1.0, and 1.1 is trivial. It&amp;#x27;s a walk in the park. It only takes about a hundred lines of code to create a proper O(n) parser. &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;jart&amp;#x2F;cosmopolitan&amp;#x2F;blob&amp;#x2F;0b317523a0875d83d650ce8a7b288e3b3500fbba&amp;#x2F;net&amp;#x2F;http&amp;#x2F;parsehttpmessage.c#L54&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;jart&amp;#x2F;cosmopolitan&amp;#x2F;blob&amp;#x2F;0b317523a0875d83d6...&lt;/a&gt;&lt;p&gt;The Joyent HTTP parser used by Node is very good but it&amp;#x27;s implemented in a way that makes the problem much more complicated than it needs to be. The biggest obstacle with high-performance HTTP message parsing is the case-insensitive string comparison of header field names. Some servers like thttpd do the naive thing and just use a long sequence of strcasecmp() statements. Joyent goes &amp;quot;fast&amp;quot; because it uses callbacks, which effectively punts the problem to the caller, and, for a few select headers which it handles itself, like Content-Length, it uses this really complicated internal &amp;quot;h_matching&amp;quot; thing for doing painstakingly written out hardcoded character compares. Redbean solves the problem by using better computer science: perfect hash tables. Thanks to gperf command. That makes the API itself much more elegant since the parser can not only go faster but return a hash-table like structure where individual headers can be indexed without performing string comparisons.</text></item><item><author>nly</author><text>No, parsing HTTP&amp;#x2F;1.x is a nightmare and definitely not simple. It wasn&amp;#x27;t even particularly well defined until 2014 when the original RFCs were modernized, and even now there are bugs reported in HTTP parsers all the time.&lt;p&gt;Node.js came out in 2009, a full ten years after HTTP&amp;#x2F;1.1 (RFC 2068) and its original http-parser is rather hard to follow, doesn&amp;#x27;t conform to the RFCs for performance reasons, and is considered unmaintainable by the author of it&amp;#x27;s replacement[0]&lt;p&gt;As for parsing HTML, well go look at how Cloudflare have stumbled[1]&lt;p&gt;[0] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;nodejs&amp;#x2F;llhttp&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;nodejs&amp;#x2F;llhttp&lt;/a&gt;&lt;p&gt;[1] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;blog.cloudflare.com&amp;#x2F;incident-report-on-memory-leak-caused-by-cloudflare-parser-bug&amp;#x2F;&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;blog.cloudflare.com&amp;#x2F;incident-report-on-memory-leak-c...&lt;/a&gt;</text></item><item><author>milansuk</author><text>That&amp;#x27;s the beauty of original HTTP - simplicity. Same as parsing HTML(in the 90s). With HTTPS(S as Secure) it&amp;#x27;s a whole different story and most programmers use some library.</text></item></parent_chain><comment><author>mariusor</author><text>I think that implementing a proper state machine for the header parsing with ragel would give a more comprehensive result than using gperf or even the handmade one from your code.&lt;p&gt;I think there are already some versions of the ragel code online, but they might be for other target programming languages.</text></comment>