{"id":255698,"date":"2017-01-12T10:32:03","date_gmt":"2017-01-12T02:32:03","guid":{"rendered":"http:\/\/blog.zhenglei.net\/?p=255698"},"modified":"2017-01-12T16:01:27","modified_gmt":"2017-01-12T08:01:27","slug":"web-development-in-c","status":"publish","type":"post","link":"https:\/\/blog.zhenglei.net\/?p=255698","title":{"rendered":"Web development in C"},"content":{"rendered":"<p><a title=\"davidmoreno\/onion\" href=\"https:\/\/github.com\/davidmoreno\/onion\" target=\"_blank\">davidmoreno\/onion<\/a><\/p>\n<p><a title=\"kore\" href=\"https:\/\/kore.io\/\" target=\"_blank\">kore<\/a><\/p>\n<p><a href=\"http:\/\/www.koanlogic.com\/klone\/index.html\" target=\"_blank\">klone<\/a><\/p>\n<p><a href=\"http:\/\/nxweb.org\/\">nxweb<\/a><\/p>\n<p>&nbsp;<\/p>\n<h1 class=\"IVILX2C-mb-y\"><strong><span id=\"t-t\" class=\"IVILX2C-mb-Y\">fast C HTTP server library comparison &amp; wishlist<\/span><\/strong><\/h1>\n<p>Hi,<\/p>\n<p>Trying to choose an embeddable HTTP server library for a project, and<br \/>\nalso considering writing my own special-purpose code, I came up with<br \/>\nthe following comparison of libonion vs. other C libraries that include<br \/>\nhigh-performance HTTP support and are currently maintained.<\/p>\n<p>Licenses:<\/p>\n<p>libevhtp+libevent &#8211; 3-clause BSD<br \/>\nlibmicrohttpd &#8211; LGPL 2.1<br \/>\nlibonion &#8211; Apache 2 (except for some examples) or GPLv2+<br \/>\nmongoose &#8211; GPLv2 (and commercial)<\/p>\n<p>Build environment:<\/p>\n<p>libevhtp+libevent &#8211; cmake+autotools<br \/>\nlibmicrohttpd &#8211; autotools<br \/>\nlibonion &#8211; cmake<br \/>\nmongoose &#8211; none (one large file, like SQLite)<\/p>\n<p>Code size (&#8220;text&#8221; as reported by the size(1) command on the library or<br \/>\non a tiny sample program if statically linked, on Scientific Linux 6.6<br \/>\non x86_64):<\/p>\n<p>libevhtp+libevent &#8211; ~500 KB, or ~200 KB without unicode.c.o and reg*.c.o<br \/>\nlibmicrohttpd &#8211; ~100 KB default, ~55 KB with most .\/configure &#8211;disable-*<br \/>\nlibonion &#8211; ~100 KB with most ONION_USE_* set to false<br \/>\nmongoose &#8211; ~100 KB including JSON-RPC<\/p>\n<p>For the smaller builds of libmicrohttpd and libonion, I kept threads<br \/>\nsupport enabled, but disabled pretty much everything else that could be<br \/>\ndisabled without patching the code. \u00a0It looks like libmicrohttpd wins<br \/>\nthis test. \u00a0Maybe there&#8217;s more code in libonion to disable (make into<br \/>\ncompile-time options) &#8211; I haven&#8217;t checked yet.<\/p>\n<p>Built-in JSON support:<\/p>\n<p>libevhtp+libevent &#8211; none<br \/>\nlibmicrohttpd &#8211; none<br \/>\nlibonion &#8211; JSON builtin, JSON-RPC in Apache 2 licensed example<br \/>\nmongoose &#8211; JSON-RPC builtin (simple JSON parser not exported?)<\/p>\n<p>All of this is for current versions on GitHub or in recent release<br \/>\ntarballs as of a few days ago.<\/p>\n<p>Maybe someone else will find this useful. \u00a0I&#8217;d appreciate corrections.<br \/>\nIt is very likely that I overlooked something.<\/p>\n<p>On a related note, I found the list of alternate implementations on the<br \/>\nlibmicrohttpd homepage very helpful. \u00a0That&#8217;s classy. \u00a0Thanks.<\/p>\n<p>My wishlist:<\/p>\n<p>A processes (pre-fork) + [e]poll mode, like nginx has. \u00a0Processes have<br \/>\npros and cons vs. threads: more reliable, faster malloc\/free (no lock<br \/>\ncontention risk), but OTOH slower context switches (if running process<br \/>\ncount exceeds number of logical CPUs). \u00a0I would likely prefer this mode,<br \/>\nbut all four libraries appear to be missing it.<\/p>\n<p>Ability to accept not only HTTP, but also raw TCP connections, and<br \/>\nhandle them in application code along with the library-handled HTTP.<br \/>\nSuch as for implementing JSON-RPC directly over TCP, while also having<br \/>\nit over TCP+HTTP, and without having to manage an own\/separate<br \/>\nthreads\/processes pool. \u00a0Do any of the four have this? \u00a0I found no such<br \/>\nexamples with any of them.<\/p>\n<p>Easily and cleanly embeddable into an application&#8217;s source tree, while<br \/>\nalso allowing easy updates to new upstream versions. \u00a0mongoose almost<br \/>\nachieves this, but at the expense of sacrificing meaningful separation<br \/>\ninto multiple translation units within the library itself. \u00a0I think we<br \/>\ndon&#8217;t have to pay this price. \u00a0We could have multiple files (10 or so?),<br \/>\nin a subdirectory, which are also easy to list in a project&#8217;s Makefile.<br \/>\nMaybe I&#8217;d do that for libonion, freeing it from cmake, but then updating<br \/>\nto new upstream versions would be harder. \u00a0Do I really have to bite the<br \/>\ncmake or\/and autotools bullet for something as simple as accepting HTTP?<\/p>\n<p>I&#8217;d prefer a more permissive license like 2-clause BSD or MIT. \u00a0But I<br \/>\nguess I&#8217;ll have to settle on Apache 2 or such. \u00a0mongoose&#8217; use of GPLv2<br \/>\nis understandable &#8211; need to make money &#8211; but is otherwise a disadvantage<br \/>\n(even for a commercial project that could pay, and even when publishing<br \/>\nany source code changes is not a problem and would be planned anyway; we<br \/>\njust don&#8217;t want to put our time into something that we would not always<br \/>\nbe able to reuse in other projects).<\/p>\n<p>Optional JSON from the same upstream is a plus, ideally exported both as<br \/>\na generic JSON parser and as JSON-RPC support. \u00a0Looks like only libonion<br \/>\nsort of delivers both (but the code might not be production quality).<\/p>\n<p>Ability to exclude more of the functionality &#8211; for example, to include<br \/>\nonly the POST method (and not compile in code for the rest). \u00a0I am<br \/>\nconcerned not so much about code size per se, as I am about attack<br \/>\nsurface, and about ease of code reviews (not having to determine if some<br \/>\ncompiled-in code is actually dead code in a given case, but to know<br \/>\nreliably that it&#8217;s not compiled in).<\/p>\n<p>On a related note, David&#8217;s use of Coverity for libonion is commendable,<br \/>\nbut it looks abandoned since 2014, and many &#8220;defects&#8221; (even if false<br \/>\npositives) remained unfixed back then.<\/p>\n<p>Mark&#8217;s use of Coverity for libevhtp is also commendable&#8230; and looks<br \/>\nabandoned since May 10, 2015. \u00a0It shows &#8220;48,919 Lines of Code Analyzed&#8221;,<br \/>\nonly &#8220;4 Total defects&#8221; and &#8220;0 Outstanding&#8221; &#8211; I guess it means that<br \/>\neverything detected by Coverity before (which must have been many more<br \/>\n&#8220;defects&#8221;) had been eliminated prior to that run. \u00a0That&#8217;s impressive.<br \/>\nBut we don&#8217;t know how many new &#8220;defects&#8221; may have appeared in the 9<br \/>\nmonths that passed. \u00a0Also, I haven&#8217;t looked into whether libevent has<br \/>\nbeen subjected to similar static analysis or not (although being<br \/>\ninitially written by Niels Provos speaks in its favor, given Niels&#8217;<br \/>\nother work), and accepting TCP connections isn&#8217;t as much risk as parsing<br \/>\nHTTP and JSON.<\/p>\n<p>I don&#8217;t give a lot of weight to the Coverity results for my<br \/>\ndecision-making, but it shows whether the maintainers care, and there<br \/>\nare few other somewhat-meaningful metrics I could use before having<br \/>\nspent time to analyze and try to use the code myself.<\/p>\n<p>Why am I posting this to the onion mailing list specifically? \u00a0I find it<br \/>\nlikely that libonion wins for me, although not by a large margin (and<br \/>\nthere&#8217;s a lot that I dislike about it). \u00a0This is not a final decision<br \/>\nyet. \u00a0I might as well end up reverting to writing special-purpose code<br \/>\nfrom scratch.<\/p>\n<p>Thanks,<\/p>\n<p>Alexander<\/p>\n","protected":false},"excerpt":{"rendered":"<p>davidmoreno\/onion kore klone nxweb &#038;nbsp &hellip; <a href=\"https:\/\/blog.zhenglei.net\/?p=255698\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,2,18],"tags":[345,344],"class_list":["post-255698","post","type-post","status-publish","format-standard","hentry","category-html","category-linux","category-software-download","tag-c","tag-web"],"_links":{"self":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=255698"}],"version-history":[{"count":4,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255698\/revisions"}],"predecessor-version":[{"id":255704,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255698\/revisions\/255704"}],"wp:attachment":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=255698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=255698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=255698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}