blob: dd6a4ac0be05133e94f902ac18851c0bfae1808e [file] [log] [blame] [raw]
<!DOCTYPE html><html><head><meta charset="utf-8" /><meta content="IE=edge" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1, maximum-scale=2.0, user-scalable=yes, minimal-ui=yes" name="viewport" /><title>facil.io - The C Web Application Framework</title><meta content="facil.io - The C Web Application Framework" name="description" /><link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand|Karla" rel="stylesheet" type="text/css" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script><link href="/assets/styles/main.css" rel="stylesheet" type="text/css" /><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://facil.io","name":"facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","keywords":"C, web, framework, websockets, websocket, realtime, real-time, easy","image":"http://facil.io/website/logo/facil-io.svg","author":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}],"sourceOrganization":{"@context":"http://schema.org","@type":"Organization","name":"Plezi","url":"http://facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","logo":"http://facil.io/website/logo/facil-io.svg","image":"http://facil.io/website/logo/facil-io.svg","email":"bo(at)facil.io","member":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}]}}</script><link href="/assets/logo/facil-io-logo.svg" rel="icon" sizes="350x350" type="image/svg" /><link href="/assets/logo/facil-io-logo.png" rel="icon" sizes="350x350" type="image/png" /><link href="/assets/logo/facil-io-logo.svg" rel="shortcut icon" sizes="350x350" type="image/svg" /><link href="/assets/logo/facil-io-logo.png" rel="shortcut icon" sizes="350x350" type="image/png" /><link href="/assets/logo/facil-io-logo.svg" rel="apple-touch-icon" sizes="350x350" type="image/svg" /><link href="/assets/logo/facil-io-logo.png" rel="apple-touch-icon" sizes="350x350" type="image/png" /><link href="/assets/logo/facil-io-logo.svg" rel="fluid-icon" sizes="350x350" type="image/svg" /><link href="/assets/logo/facil-io-logo.png" rel="fluid-icon" sizes="350x350" type="image/png" /><link href="/manifest.json" rel="manifest" /><meta content="facil.io" name="apple-mobile-web-app-title" /><meta content="facil.io - the C Web Application Framework" name="application-name" /><meta content="#b91d47" name="msapplication-TileColor" /><meta content="/mstile-144x144.png" name="msapplication-TileImage" /><meta content="#ffffff" name="theme-color" /></head><body><a href="/" id="logo"></a><input id="show_nav" type="checkbox" /><nav id="top_nav"><ul><li><a href="/0.7.x/index">Latest Docs</a></li><li><a href="https://github.com/boazsegev/facil.io" target="_blank">Source Code</a></li><li><a href="javascript: change_themes();" id="theme">Night Theme</a></li></ul></nav><input id="show_sidebar" type="checkbox" /><nav id="side_bar"><h2 id="documentation">Documentation</h2>
<p>Please choose the relevant facil.io version to read it&#39;s documentation:</p>
<ul>
<li><p><a href="/0.7.x/index">0.7.x</a> (edge)</p></li>
<li><p><a href="/0.6.x/index">0.6.x</a> (stable)</p></li>
</ul>
<h2 id="versions">Versions</h2>
<p>Review the <a href="changelog">change-log</a> when migrating between versions.</p>
<ul>
<li><p><a href="changelog">Change Log</a></p></li>
<li><p><strong>Latest (beta)</strong>: 0.7.0.beta7</p></li>
<li><p><strong>Latest stable</strong>: 0.6.4</p></li>
</ul>
</nav><div id="md_container"><h1 id="facil-io-the-c-web-application-framework">facil.io - The C Web Application Framework</h1>
<ul>
<li><p><a href="http://facil.io">facil.io</a> is an evented Network library written in C.</p>
<p><a href="http://facil.io">facil.io</a> provides high performance TCP/IP network services by using an evented design that was tested to provide an easy solution to <a href="http://www.kegel.com/c10k.html">the C10K problem</a>.</p></li>
<li><p><a href="http://facil.io">facil.io</a> includes a mini-framework for Web Applications, with a fast HTTP / WebSocket server, integrated Pub/Sub, optional Redis connectivity, easy JSON handling, <a href="http://mustache.github.io">Mustache</a> template rendering and more nifty tidbits.</p></li>
<li><p><a href="http://facil.io">facil.io</a> powers the <a href="https://github.com/boazsegev/iodine">HTTP/Websockets Ruby Iodine server</a> and it can easily power your application as well.</p></li>
<li><p><a href="http://facil.io">facil.io</a> is easy to code with and aims at minimizing the developer&#39;s learning curve.</p>
<p>In addition to detailed documentation and examples, the API is unified in style and the same types and API used for HTTP requests is used for JSON and Mustache rendering - so there&#39;s less to learn.</p></li>
<li><p><a href="http://facil.io">facil.io</a> should work on Linux / BSD / macOS (and possibly CYGWIN) and is continuously tested on both Linux and macOS.</p></li>
<li><p><a href="http://facil.io">facil.io</a> supports both single-threaded and multi-threaded operation modes as well as a hybrid mode (multi-process with either a single-threaded or multi-threaded workers).</p></li>
<li><p><a href="http://facil.io">facil.io</a> is a source code library, making it easy to incorporate into any project. The API was designed for simplicity and extendability, which means writing new extensions and custom network protocols is easy.</p></li>
</ul>
<p>I used this library (including the HTTP server) on Linux, Mac OS X and FreeBSD (I had to edit the <code>makefile</code> for each environment).</p>
<h3 id="a-web-application-in-c-its-as-easy-as">A Web application in C? It&#39;s as easy as...</h3>
<div class="highlight"><pre class="highlight c"><code><span class="cp">#include "http.h" </span><span class="cm">/* the HTTP facil.io extension */</span><span class="cp">
</span>
<span class="c1">// We'll use this callback in `http_listen`, to handles HTTP requests</span>
<span class="kt">void</span> <span class="n">on_request</span><span class="p">(</span><span class="n">http_s</span> <span class="o">*</span><span class="n">request</span><span class="p">);</span>
<span class="c1">// These will contain pre-allocated values that we will use often</span>
<span class="n">FIOBJ</span> <span class="n">HTTP_HEADER_X_DATA</span><span class="p">;</span>
<span class="c1">// Listen to HTTP requests and start facil.io</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// allocating values we use often</span>
<span class="n">HTTP_HEADER_X_DATA</span> <span class="o">=</span> <span class="n">fiobj_str_new</span><span class="p">(</span><span class="s">"X-Data"</span><span class="p">,</span> <span class="mi">6</span><span class="p">);</span>
<span class="c1">// listen on port 3000 and any available network binding (NULL == 0.0.0.0)</span>
<span class="n">http_listen</span><span class="p">(</span><span class="s">"3000"</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="p">.</span><span class="n">on_request</span> <span class="o">=</span> <span class="n">on_request</span><span class="p">,</span> <span class="p">.</span><span class="n">log</span> <span class="o">=</span> <span class="mi">1</span><span class="p">);</span>
<span class="c1">// start the server</span>
<span class="n">fio_start</span><span class="p">(.</span><span class="n">threads</span> <span class="o">=</span> <span class="mi">1</span><span class="p">);</span>
<span class="c1">// deallocating the common values</span>
<span class="n">fiobj_free</span><span class="p">(</span><span class="n">HTTP_HEADER_X_DATA</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Easy HTTP handling</span>
<span class="kt">void</span> <span class="nf">on_request</span><span class="p">(</span><span class="n">http_s</span> <span class="o">*</span><span class="n">request</span><span class="p">)</span> <span class="p">{</span>
<span class="n">http_set_cookie</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"my_cookie"</span><span class="p">,</span> <span class="p">.</span><span class="n">name_len</span> <span class="o">=</span> <span class="mi">9</span><span class="p">,</span> <span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="s">"data"</span><span class="p">,</span>
<span class="p">.</span><span class="n">value_len</span> <span class="o">=</span> <span class="mi">4</span><span class="p">);</span>
<span class="n">http_set_header</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">HTTP_HEADER_CONTENT_TYPE</span><span class="p">,</span>
<span class="n">http_mimetype_find</span><span class="p">(</span><span class="s">"txt"</span><span class="p">,</span> <span class="mi">3</span><span class="p">));</span>
<span class="n">http_set_header</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">HTTP_HEADER_X_DATA</span><span class="p">,</span> <span class="n">fiobj_str_new</span><span class="p">(</span><span class="s">"my data"</span><span class="p">,</span> <span class="mi">7</span><span class="p">));</span>
<span class="n">http_send_body</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s">"Hello World!</span><span class="se">\r\n</span><span class="s">"</span><span class="p">,</span> <span class="mi">14</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p><em>(Written using version 0.7.0)</em></p>
<h3 id="creating-a-web-application-using-facil-io">Creating a Web Application Using facil.io</h3>
<p>Starting a new application with facil.io is as easy as <a href="https://github.com/boazsegev/facil.io">downloading a copy of facil.io from GitHub</a>.</p>
<p>To make things easier, <a href="https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app">a script</a> is provided.</p>
<div class="highlight"><pre class="highlight shell"><code>bash &lt;<span class="o">(</span>curl <span class="nt">-s</span> https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app<span class="o">)</span> appname
</code></pre></div>
<p>By default, this script downloads the latest release, which may or may not be what you want.</p>
<p>It&#39;s possible to download a specific release or branch, (for example, the latest 0.6.x release, 0.6.4) using <code>FIO_RELEASE</code> or <code>FIO_BRANCH</code>.</p>
<p>i.e., download the latest <strong>stable</strong> release, version 0.6.4:</p>
<div class="highlight"><pre class="highlight shell"><code><span class="nv">FIO_RELEASE</span><span class="o">=</span>0.6.4 bash &lt;<span class="o">(</span>curl <span class="nt">-s</span> https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app<span class="o">)</span> appname
</code></pre></div>
<p>i.e., or download the latest development (edge) version from the <code>master</code> branch:</p>
<div class="highlight"><pre class="highlight shell"><code><span class="nv">FIO_BRANCH</span><span class="o">=</span>master bash &lt;<span class="o">(</span>curl <span class="nt">-s</span> https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app<span class="o">)</span> appname
</code></pre></div>
<hr>
<h2 id="forking-contributing-and-all-that-jazz">Forking, Contributing and all that Jazz</h2>
<p>Sure, why not.</p>
<p>If you encounter any issues, open an issue (or, even better, a pull request with a fix) - that would be great :-)</p>
<p>Hit me up if you want to:</p>
<ul>
<li><p>Help me write HPACK / HTTP2 protocol support.</p></li>
<li><p>Help me design / write a generic HTTP routing helper library for the <code>http_s</code> struct.</p></li>
<li><p>If you want to help integrate an SSL/TLS library into <code>facil</code>, that would be great.</p></li>
<li><p>If you can add Solaris or Windows completion ports support (to be added to <code>fio.c</code>). This could improve facil.io&#39;s performance on these platforms (which currently fallback on <code>poll</code>).</p></li>
</ul>
</div><a href="/" id="sign"></a><div class="hidden" id="notice"><a class="notice_close" onclick="hide_notice()">X</a><div id="notice_text"></div></div><script>function change_themes() {
if(localStorage.getItem("theme") == 'dark') {
localStorage.setItem("theme", "light");
} else {
localStorage.setItem("theme", "dark");
}
$('body')[0].className = localStorage.getItem("theme");
set_theme_link();
$('#show_nav').attr('checked', false);
return false;
};
function sidebar_name() { return window.location.pathname.slice(0, window.location.pathname.lastIndexOf("/")); }
function on_sidebar_link(e) {
sessionStorage.setItem("sidebar.expect", sidebar_name());
sessionStorage.setItem("sidebar.pos", document.getElementById("side_bar").scrollTop);
}
function load_sidebar_pos() {
var e = document.getElementById("side_bar");
if(!e) {
console.warn("No sidebar detected");
return;
}
var expect = sidebar_name();
if(sessionStorage.getItem("sidebar.expect") == expect) {
e.scrollTo(0, parseInt(sessionStorage.getItem("sidebar.pos")));
} else {
sessionStorage.setItem("sidebar.expect", false);
sessionStorage.setItem("sidebar.pos", 0);
}
if(e) {
// add link callbacks
var links = document.links;
var count = links.length;
for (var i = 0; i < count; i++) {
var href = links[i].href;
if(href.startsWith(document.location.origin)) {
href = href.slice(document.location.origin.length);
}
if(href.startsWith(expect)) {
/* add link event */
links[i].addEventListener("click", on_sidebar_link);
}
}
}
};
load_sidebar_pos();
function set_theme_link() {
$("#theme").html( ( (localStorage.getItem("theme") == 'dark') ? "Day" : "Night") + " Theme" );
}
$('body')[0].className = (localStorage.getItem("theme") == 'dark') ? "dark" : "light";
set_theme_link();
function show_notice() { document.getElementById("notice").classList.remove('hidden'); };
function hide_notice() { document.getElementById("notice").classList.add('hidden'); };
$('#toc').on("touchstart", function (e) { return true; } );
$('#toc').on("hover", function (e) { return true; } );
// hljs.initHighlighting();
// Google Analytics
// if(location.hostname != "localhost") {
// (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
// })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
// ga('create', 'UA-69931401-1', 'auto');
// ga('send', 'pageview');
// }</script></body></html>