UNPKG

node-http-server

Version:

A very simple and fast http server for node, bash, and spawnable from C, Python etc. It is lightweight and great for embedded solutions as well as everyday development or public facing apps.

976 lines (893 loc) 50.9 kB
<!DOCTYPE html> <html> <head> <title>Node http server with https and proxy support</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <link rel="stylesheet" media="all" href="assets/file_1.css"/> <link rel="stylesheet" media="all" href="assets/file_5.css"/> <link rel="stylesheet" media="all" href="assets/32px.png"/> <link rel="stylesheet" media="all" href="assets/40px.png"/> <link rel="stylesheet" media="all" href="assets/throbber.gif"/> <link rel="stylesheet" media="all" href="assets/file_7.css"/> <link rel="stylesheet" media="all" href="assets/file_8.css"/> <script src="assets/file_2.js" type="text/javascript"></script> <script src="assets/file_3.js" type="text/javascript"></script> <script src="assets/file_4.js" type="text/javascript"></script> <script src="assets/file_6.js" type="text/javascript"></script> <script type="application/json" id="jsTreeJSON"> [{"id":"./example/basic/https-advancedApp.js","text":"https-advancedApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-advancedApp.js.html"},"state":{"selected":false}},{"id":".","text":".","icon":"jstree-folder","parent":"#","a_attr":{"href":"."},"state":{"opened":true}},{"id":"./example","text":"example","icon":"jstree-folder","parent":".","a_attr":{"href":"example"},"state":{"opened":false}},{"id":"./example/readme.md","text":"readme.md","icon":"jstree-file","parent":"./example","a_attr":{"href":"example/readme.md.html"},"state":{"selected":false}},{"id":"./example/advanced","text":"advanced","icon":"jstree-folder","parent":"./example","a_attr":{"href":"example/advanced"},"state":{"opened":false}},{"id":"./example/advanced/basicTemplate.js","text":"basicTemplate.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/basicTemplate.js.html"},"state":{"selected":false}},{"id":"./example/advanced/https-ONLY-basicTemplate.js","text":"https-ONLY-basicTemplate.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/https-ONLY-basicTemplate.js.html"},"state":{"selected":false}},{"id":"./example/advanced/https-basicTemplate.js","text":"https-basicTemplate.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/https-basicTemplate.js.html"},"state":{"selected":false}},{"id":"./example/advanced/https-randomCSS.js","text":"https-randomCSS.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/https-randomCSS.js.html"},"state":{"selected":false}},{"id":"./example/advanced/https-requestBenchmark.js","text":"https-requestBenchmark.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/https-requestBenchmark.js.html"},"state":{"selected":false}},{"id":"./example/advanced/randomCSS.js","text":"randomCSS.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/randomCSS.js.html"},"state":{"selected":false}},{"id":"./example/advanced/requestBenchmark.js","text":"requestBenchmark.js","icon":"jstree-file","parent":"./example/advanced","a_attr":{"href":"example/advanced/requestBenchmark.js.html"},"state":{"selected":false}},{"id":"./example/basic","text":"basic","icon":"jstree-folder","parent":"./example","a_attr":{"href":"example/basic"},"state":{"opened":false}},{"id":"./example/basic/advancedApp.js","text":"advancedApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/advancedApp.js.html"},"state":{"selected":false}},{"id":"./example/basic/basicApp.js","text":"basicApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/basicApp.js.html"},"state":{"selected":false}},{"id":"./example/basic/basicLogging.js","text":"basicLogging.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/basicLogging.js.html"},"state":{"selected":false}},{"id":"./example/basic/cluster-basicApp.js","text":"cluster-basicApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/cluster-basicApp.js.html"},"state":{"selected":false}},{"id":"./example/basic/https-ONLY-basicApp.js","text":"https-ONLY-basicApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-ONLY-basicApp.js.html"},"state":{"selected":false}},{"id":"./README.md","text":"README.md","icon":"jstree-file","parent":".","a_attr":{"href":"README.md.html"},"state":{"selected":true}},{"id":"./example/basic/https-basicApp.js","text":"https-basicApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-basicApp.js.html"},"state":{"selected":false}},{"id":"./example/basic/https-basicLogging.js","text":"https-basicLogging.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-basicLogging.js.html"},"state":{"selected":false}},{"id":"./example/basic/https-multipleDomains.js","text":"https-multipleDomains.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-multipleDomains.js.html"},"state":{"selected":false}},{"id":"./example/basic/https-verboseApp.js","text":"https-verboseApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/https-verboseApp.js.html"},"state":{"selected":false}},{"id":"./example/basic/multipleDomains.js","text":"multipleDomains.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/multipleDomains.js.html"},"state":{"selected":false}},{"id":"./example/basic/verboseApp.js","text":"verboseApp.js","icon":"jstree-file","parent":"./example/basic","a_attr":{"href":"example/basic/verboseApp.js.html"},"state":{"selected":false}},{"id":"./example/proxy","text":"proxy","icon":"jstree-folder","parent":"./example","a_attr":{"href":"example/proxy"},"state":{"opened":false}},{"id":"./example/proxy/basic.js","text":"basic.js","icon":"jstree-file","parent":"./example/proxy","a_attr":{"href":"example/proxy/basic.js.html"},"state":{"selected":false}},{"id":"./example/proxy/https-and-http-basic.js","text":"https-and-http-basic.js","icon":"jstree-file","parent":"./example/proxy","a_attr":{"href":"example/proxy/https-and-http-basic.js.html"},"state":{"selected":false}},{"id":"./example/proxy/https-and-http-google-proxy.js","text":"https-and-http-google-proxy.js","icon":"jstree-file","parent":"./example/proxy","a_attr":{"href":"example/proxy/https-and-http-google-proxy.js.html"},"state":{"selected":false}},{"id":"./server","text":"server","icon":"jstree-folder","parent":".","a_attr":{"href":"server"},"state":{"opened":false}},{"id":"./server/Config.js","text":"Config.js","icon":"jstree-file","parent":"./server","a_attr":{"href":"server/Config.js.html"},"state":{"selected":false}},{"id":"./server/Server.js","text":"Server.js","icon":"jstree-file","parent":"./server","a_attr":{"href":"server/Server.js.html"},"state":{"selected":false}},{"id":"./bin","text":"bin","icon":"jstree-folder","parent":".","a_attr":{"href":"bin"},"state":{"opened":false}},{"id":"./bin/nhs.js","text":"nhs.js","icon":"jstree-file","parent":"./bin","a_attr":{"href":"bin/nhs.js.html"},"state":{"selected":false}},{"id":"./local-certs","text":"local-certs","icon":"jstree-folder","parent":".","a_attr":{"href":"local-certs"},"state":{"opened":false}},{"id":"./local-certs/readme.md","text":"readme.md","icon":"jstree-file","parent":"./local-certs","a_attr":{"href":"local-certs/readme.md.html"},"state":{"selected":false}}] </script> </head> <body class="markdown-body"> <h1> Node http server with https and proxy support </h1> <div class="subHeading"> ./README.md </div> <button type="button" class="navigatorToggle">&#9776; files...</button> <nav class="navigationTree minimized"> <input type="text" id="jsTreeSearch" placeholder="search..."/> <div></div> </nav> <section> <ul class="sectionDetails docsOnly"> <li id="section-1"> <div class="annotation"> <hr> <p>Simple to use stand alone node HTTP and HTTPS Server you can spin up in seconds.</p> <ul> <li><strong><em><a href="#examples">TLDR; Quick start examples</a></em></strong></li> <li><strong><em><a href="#server-class">Server Class</a></em></strong></li> <li><strong><em><a href="#config-class">Config Class</a></em></strong></li> <li><strong><em><a href="#basic-cluster-server">Basic use with cluster example</a></em></strong></li> </ul> <p>Support for building proxy servers has been added. Documentation coming in next release. <a href="https://github.com/RIAEvangelist/node-http-server/tree/master/example/proxy">For now see the node-http-server proxy examples</a>.</p> <p><code>npm i node-http-server</code></p> <p>npm info : <a href="http://npm-stat.com/charts.html?package=node-http-server&amp;author=&amp;from=&amp;to=">See npm trends and stats for node-http-server</a><br><img src="https://img.shields.io/npm/v/node-http-server.svg" alt="node-http-server npm version"> <img src="https://img.shields.io/node/v/node-http-server.svg" alt="supported node version for node-http-server"> <img src="https://img.shields.io/npm/dt/node-http-server.svg" alt="total npm downloads for node-http-server"> <img src="https://img.shields.io/npm/dm/node-http-server.svg" alt="monthly npm downloads for node-http-server"> <img src="https://img.shields.io/npm/l/node-http-server.svg" alt="npm licence for node-http-server"></p> <p>GitHub info :<br><img src="https://img.shields.io/github/release/RIAEvangelist/node-http-server.svg" alt="node-http-server GitHub Release"> <img src="https://img.shields.io/github/license/RIAEvangelist/node-http-server.svg" alt="GitHub license node-http-server license"> <img src="https://img.shields.io/github/issues/RIAEvangelist/node-http-server.svg" alt="open issues for node-http-server on GitHub"> <a href="https://www.codacy.com/app/RIAEvangelist/node-http-server?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=RIAEvangelist/node-http-server&amp;utm_campaign=badger"><img src="https://api.codacy.com/project/badge/Grade/fbfd39a7b56643d290bb93db61b14db3" alt="Codacy Badge"></a> </p> <p><a href="https://www.npmjs.com/package/node-http-server"><img src="https://nodei.co/npm/node-http-server.png?downloads=true&amp;downloadRank=true&amp;stars=true" alt="node-http-server stats"></a></p> <p>Package Quality :<br><img src="http://npm.packagequality.com/badge/node-http-server.png" alt="node-http-server Package Quality"></p> <p><a href="http://riaevangelist.github.io/node-http-server/">See the code documentation on riaevangelist.github.io</a></p> <h2 id="cli-use-if-you-just-want-to-test">cli use if you just want to test</h2> <p>Now you can also use the node-http-server cli if you just want to spin up a basic file server to test something out quickly or share on the local network.</p> <pre><code class="lang-sh"> $ sudo npm i -g node-http-server //start a node-http-server from the current directory on the default port 8080 $ node-http-server </code></pre> <p>You can modify any of the config keys by passing their key value pairs as args.</p> <pre><code class="lang-sh"> //start a verbose node-http-server from the current directory on port 1942 $ node-http-server port=1942 verbose=<span class="hljs-literal">true</span> </code></pre> <h3 id="quick-npm-script-tests-and-examples">quick npm script tests and examples</h3> <pre><code class="lang-sh"> <span class="hljs-comment">#node ./example/basic/basicApp.js</span> npm run basic <span class="hljs-comment">#node ./example/basic/https-ONLY-basicApp.js</span> npm run https <span class="hljs-comment">#node ./example/basic/https-basicApp.js</span> npm run both <span class="hljs-comment">#node ./example/advanced/basicTemplate.js</span> npm run template <span class="hljs-comment">#node ./example/basic/cluster-basicApp.js</span> npm run cluster </code></pre> <h2 id="writing-a-node-http-or-https-server">writing a node http or https server</h2> <p>The below table shows all of the methods available on the server when you require this module.</p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.deploy(); </code></pre> <p>If you want to create a custom Server or extend the Server Class you can require just the server class.</p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> Server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>).Server; <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCustomServer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Server</span></span>{ <span class="hljs-keyword">constructor</span>(){ <span class="hljs-keyword">super</span>(); } } <span class="hljs-keyword">const</span> server=<span class="hljs-keyword">new</span> MyCustomServer; server.deploy(); </code></pre> <h2 id="server-class">Server Class</h2> <table> <thead> <tr> <th>Server Method or member</th> <th>params</th> <th>returns / should return</th> <th>description</th> </tr> </thead> <tbody> <tr> <td><a href="#deploy">deploy</a></td> <td><code>userConfig</code> obj (optional), <code>readyCallback</code> fn (optional)</td> <td>returns void</td> <td>Starts the server. if a config object is passed it will shallow merge it with a clean instantion of the Config class.</td> </tr> <tr> <td><a href="#onrawrequest">onRawRequest</a></td> <td><code>request</code> obj, <code>response</code> obj, <code>serve</code> fn</td> <td>should return true,false or void</td> <td>Called immediately upon reciept of http(s) request. Called before any request parsing, useful for <code>proxy servers</code> and request modification, high speed handling, or rejection. Mildly more complex to work with because the request object has not been parsed and decorated with helper members. If this function returns true, the servers response lifecycle will be exited and you must manually call serve. this allows manual immediate and manual async serving. use the <code>serve</code> argument, <code>server.serve</code> or <code>server.serveFile</code> to manually serve the response.</td> </tr> <tr> <td><a href="#onrequest">onRequest</a></td> <td><code>request</code> obj, <code>response</code> obj, <code>serve</code> fn</td> <td>should return true,false or void</td> <td>Called when request received. If this function returns true, the servers response lifecycle will be exited and you must manually call serve. this allows manual immediate and manual async serving. use the <code>serve</code> argument, <code>server.serve</code> or <code>server.serveFile</code> to manually serve the response.</td> </tr> <tr> <td><a href="#beforeserve">beforeServe</a></td> <td><code>request</code> obj, <code>response</code> obj, <code>body</code> obj, <code>encoding</code> obj, <code>serve</code> fn</td> <td>should return true,false or void</td> <td>Called just before data is served to the client. If this function returns true, the servers response lifecycle will be exited and you must manually call serve. this allows manual immediate and manual async serving. use the <code>serve</code> argument, <code>server.serve</code> or <code>server.serveFile</code> to manually serve the response.</td> </tr> <tr> <td><a href="#afterserve">afterServe</a></td> <td><code>request</code> obj</td> <td>void</td> <td>Called once data has been fully sent to client.</td> </tr> <tr> <td><a href="#config-class">Config</a></td> <td>n/a</td> <td>n/a</td> <td>This is a reference to the Default Config class. Use it to generate a complete config file based off of the default values and arguments passed in when launching the app. Will perform a shallow merge of default values and passed values if a config object passed.</td> </tr> <tr> <td><a href="#server-class">Server</a></td> <td>n/a</td> <td>n/a</td> <td>This is a reference to the Server Class. Use it to start multiple servers on different ports or to extend the node-http-server.</td> </tr> </tbody> </table> <h2 id="request-uri-query-and-body">request uri, query, and, body</h2> <p>For handling api requests, posts, puts patches etc with body data, we are now making that available on the request as both a <code>String</code> and <code>Buffer</code> incase you need images or videos uploaded.</p> <table> <thead> <tr> <th>key</th> <th>type</th> <th>value</th> </tr> </thead> <tbody> <tr> <td>request.body</td> <td>string</td> <td>request body</td> </tr> <tr> <td>request.url</td> <td>string</td> <td>processed uri</td> </tr> <tr> <td>request.uri</td> <td>object</td> <td>parsed url information and query</td> </tr> <tr> <td>request.serverRoot</td> <td>string</td> <td>local dir for publicly served data</td> </tr> </tbody> </table> <table> <thead> <tr> <th>key</th> <th>type</th> <th>value</th> </tr> </thead> <tbody> <tr> <td>uri.protocol</td> <td>string</td> <td>protocol of request</td> </tr> <tr> <td>uri.host</td> <td>string</td> <td>hostname for domain</td> </tr> </tbody> </table> <p>uri.hostname |string| hostname for domain| |uri.query |object| parsed querystring| |uri.port |number| port request was received on|</p> <h3 id="-server-methods-http-riaevangelist-github-io-node-http-server-server-server-js-html-"><a href="http://riaevangelist.github.io/node-http-server/server/Server.js.html">Server Methods</a></h3> <h4 id="deploy">deploy</h4> <p><code>server.deploy</code> starts the server.</p> <p><code>server.deploy(userConfig,readyCallback)</code></p> <table> <thead> <tr> <th>method</th> <th>returns</th> </tr> </thead> <tbody> <tr> <td>deploy</td> <td>void</td> </tr> </tbody> </table> <table> <thead> <tr> <th>parameter</th> <th>required</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>userConfig</td> <td>no</td> <td>if a <code>userConfig</code> object is passed it will decorate the <a href="http://riaevangelist.github.io/node-http-server/server/Config.js.html">Config class</a></td> </tr> <tr> <td>readyCallback</td> <td>no</td> <td>called once the server is started</td> </tr> </tbody> </table> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">'~/myApp/'</span> }, serverReady ); server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8888</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">'~/myOtherApp/'</span> }, serverReady ); <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverReady</span>(<span class="hljs-params">server</span>)</span>{ <span class="hljs-built_in">console</span>.log( <span class="hljs-string">`Server on port <span class="hljs-subst">${server.config.port}</span> is now up`</span>); } </code></pre> <h4 id="onrawrequest">onRawRequest</h4> <p><code>server.onRawRequest</code></p> <p><code>server.onRawRequest(request,response,serve)</code></p> <table> <thead> <tr> <th>method</th> <th>should return</th> </tr> </thead> <tbody> <tr> <td>onRawRequest</td> <td>bool/void</td> </tr> </tbody> </table> <table> <thead> <tr> <th>parameter</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>request</td> <td>http(s) request obj</td> </tr> <tr> <td>response</td> <td>http(s) response obj</td> </tr> <tr> <td>serve</td> <td>ref to <code>server.serve</code></td> </tr> </tbody> </table> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config=<span class="hljs-keyword">new</span> server.Config; config.port=<span class="hljs-number">8000</span>; server.onRawRequest=gotRequest; server.deploy(config); <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gotRequest</span>(<span class="hljs-params">request,response,serve</span>)</span>{ <span class="hljs-built_in">console</span>.log(request.uri,request.headers); serve( request, response, <span class="hljs-built_in">JSON</span>.stringify( { <span class="hljs-attr">uri</span>:request.uri, <span class="hljs-attr">headers</span>:request.headers } ) ); <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; } </code></pre> <h4 id="onrequest">onRequest</h4> <p><code>server.onRequest</code></p> <p><code>server.onRequest(request,response,serve)</code></p> <table> <thead> <tr> <th>method</th> <th>should return</th> </tr> </thead> <tbody> <tr> <td>onRequest</td> <td>bool/void</td> </tr> </tbody> </table> <table> <thead> <tr> <th>parameter</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>request</td> <td>http(s) request obj</td> </tr> <tr> <td>response</td> <td>http(s) response obj</td> </tr> <tr> <td>serve</td> <td>ref to <code>server.serve</code></td> </tr> </tbody> </table> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config=<span class="hljs-keyword">new</span> server.Config; config.port=<span class="hljs-number">8099</span>; config.verbose=<span class="hljs-literal">true</span>; server.onRequest=gotRequest; server.deploy(config); <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gotRequest</span>(<span class="hljs-params">request,response,serve</span>)</span>{ <span class="hljs-comment">//at this point the request is decorated with helper members lets take a look at the query params if there are any.</span> <span class="hljs-built_in">console</span>.log(request.query,request.uri,request.headers); <span class="hljs-comment">//lets only let the requests with a query param of hello go through</span> <span class="hljs-keyword">if</span>(request.query.hello){ <span class="hljs-comment">// remember returning false means do not inturrupt the response lifecycle</span> <span class="hljs-comment">// and that you will not be manually serving</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; } serve( request, response, <span class="hljs-built_in">JSON</span>.stringify( { <span class="hljs-attr">success</span>:<span class="hljs-literal">false</span>, <span class="hljs-attr">message</span>:<span class="hljs-string">'you must have a query param of hello to access the server i.e. /index.html?hello'</span> uri:request.uri, <span class="hljs-attr">query</span>:request.query } ) ); <span class="hljs-comment">//now we let the server know we want it to kill the normal request lifecycle</span> <span class="hljs-comment">//because we just completed it by serving above. we could also handle it async style</span> <span class="hljs-comment">//and request a meme or something from the web and put that on the page (or something...)</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; } </code></pre> <h4 id="beforeserve">beforeServe</h4> <p><code>server.beforeServe</code></p> <p><code>server.beforeServe(request,response,body,encoding,serve)</code></p> <table> <thead> <tr> <th>method</th> <th>should return</th> </tr> </thead> <tbody> <tr> <td>beforeServe</td> <td>bool/void</td> </tr> </tbody> </table> <table> <thead> <tr> <th>parameter</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>request</td> <td>http(s) request obj</td> </tr> <tr> <td>response</td> <td>http(s) response obj</td> </tr> <tr> <td>body</td> <td>response content body RefString</td> </tr> <tr> <td>encoding</td> <td>response body encoding RefString</td> </tr> <tr> <td>serve</td> <td>ref to <code>server.serve</code></td> </tr> </tbody> </table> <p>type <code>RefString</code></p> <table> <thead> <tr> <th>type</th> <th>keys</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>RefString</td> <td><code>value</code></td> <td>a way to allow modifying a string by refrence.</td> </tr> </tbody> </table> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.beforeServe=beforeServe; <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">beforeServe</span>(<span class="hljs-params">request,response,body,encoding</span>)</span>{ <span class="hljs-comment">//only parsing html files for this example</span> <span class="hljs-keyword">if</span>(response.getHeader(<span class="hljs-string">'Content-Type'</span>)!=server.config.contentType.html){ <span class="hljs-comment">//return void||false to allow response lifecycle to continue as normal</span> <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">const</span> someVariable=<span class="hljs-string">'this is some variable value'</span>; body.value=body.value.replace(<span class="hljs-string">'{{someVariable}}'</span>,someVariable); <span class="hljs-comment">//return void||false to allow response lifecycle to continue as normal</span> <span class="hljs-comment">//with modified body content</span> <span class="hljs-keyword">return</span>; } server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/appRoot/`</span> } ); </code></pre> <h4 id="afterserve">afterServe</h4> <p><code>server.afterServe</code></p> <p><code>server.afterServe(request)</code></p> <table> <thead> <tr> <th>method</th> <th>should return</th> </tr> </thead> <tbody> <tr> <td>afterServe</td> <td>n/a</td> </tr> </tbody> </table> <table> <thead> <tr> <th>parameter</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>request</td> <td>decorated http(s) request obj</td> </tr> </tbody> </table> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.afterServe=afterServe; <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">afterServe</span>(<span class="hljs-params">request</span>)</span>{ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`just served <span class="hljs-subst">${request.uri}</span>`</span>); } server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8075</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/appRoot/`</span> } ); </code></pre> <h2 id="examples">Examples</h2> <p>To see the node http server in action run <code>npm start</code> from the root of this repo and then visit <a href="http://localhost:8000">localhost:8000</a>.</p> <p>To start only an https example server <code>npm run https</code> from the root of this repo and then visit <a href="http://localhost:4433">localhost:4433</a>.</p> <p>To spin up both an http and an https server <code>npm run both</code> from the root of this repo and then visit <a href="http://localhost:4433">localhost:4433</a> or <a href="http://localhost:8000">localhost:8000</a>.</p> <p>Detailed examples can be found in the <a href="https://github.com/RIAEvangelist/node-http-server/tree/master/example">example folder</a> or under the example folder on the <a href="http://riaevangelist.github.io/node-http-server/example/readme.md.html">node-http-server example docs</a> The basic example directory is static http and https file servers and the advanced directory has dynamic server side rendering http and https examples including a benchmark example. The <code>proxy</code> examples show manual serving and response modification examples. </p> <h1 id="basic-http-server-example">Basic http server example</h1> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">'~/myApp/'</span> } ); </code></pre> <h1 id="basic-https-only-server-example">Basic https only server example</h1> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">'~/myApp/'</span>, <span class="hljs-attr">https</span>:{ <span class="hljs-attr">privateKey</span>:<span class="hljs-string">`/path/to/your/certs/private/server.key`</span>, <span class="hljs-attr">certificate</span>:<span class="hljs-string">`/path/to/your/certs/server.pub`</span>, <span class="hljs-attr">port</span>:<span class="hljs-number">4433</span>, <span class="hljs-attr">only</span>:<span class="hljs-literal">true</span> } } ); </code></pre> <h1 id="basic-server-running-both-http-and-https">Basic server running both http and https</h1> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">'~/myApp/'</span>, <span class="hljs-attr">https</span>:{ <span class="hljs-attr">privateKey</span>:<span class="hljs-string">`/path/to/your/certs/private/server.key`</span>, <span class="hljs-attr">certificate</span>:<span class="hljs-string">`/path/to/your/certs/server.pub`</span>, <span class="hljs-attr">port</span>:<span class="hljs-number">4433</span> } } ); </code></pre> <h2 id="basic-cluster-server">Basic cluster server</h2> <pre><code class="lang-javascript"> <span class="hljs-comment">//import the `node-http-server` module</span> <span class="hljs-comment">//` const server=require(‘node-http-server’); `</span> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'../../server/Server.js'</span>); <span class="hljs-comment">//import cluster</span> <span class="hljs-keyword">const</span> cluster = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cluster'</span>); <span class="hljs-keyword">const</span> numCPUs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'os'</span>).cpus().length; <span class="hljs-keyword">if</span> (cluster.isMaster) { <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Master <span class="hljs-subst">${process.pid}</span> is running`</span>); <span class="hljs-comment">// Fork node-http-server cluster workers.</span> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numCPUs; i++) { cluster.fork(); } cluster.on( <span class="hljs-string">'exit'</span>, (worker, code, signal) =&gt; { <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`worker <span class="hljs-subst">${worker.process.pid}</span> died`</span>); } ); } <span class="hljs-keyword">else</span> { server.afterServe=<span class="hljs-function">(<span class="hljs-params">request</span>)=&gt;</span>{ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${process.pid}</span> served <span class="hljs-subst">${request.uri.path}</span>`</span>); } <span class="hljs-comment">//start server in clustered children</span> server.deploy( { <span class="hljs-attr">verbose</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">port</span>: <span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:__dirname+<span class="hljs-string">'/appRoot/'</span> } ); <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Worker <span class="hljs-subst">${process.pid}</span> started listening on <span class="hljs-subst">${server.config.port}</span>`</span>); } </code></pre> <h2 id="template-filling">Template filling</h2> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); server.beforeServe=beforeServe; <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">beforeServe</span>(<span class="hljs-params">request,response,body,encoding</span>)</span>{ <span class="hljs-comment">//only parsing html files for this example</span> <span class="hljs-keyword">if</span>(response.getHeader(<span class="hljs-string">'Content-Type'</span>)!=server.config.contentType.html){ <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">const</span> someVariable=<span class="hljs-string">'this is some variable value'</span>; body.value=body.value.replace(<span class="hljs-string">'{{someVariable}}'</span>,someVariable); } server.deploy( { <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/appRoot/`</span> } ); </code></pre> <hr> <h2 id="custom-configuration">Custom configuration</h2> <p>for http :</p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config=<span class="hljs-keyword">new</span> server.Config; config.errors[<span class="hljs-string">'404'</span>] = <span class="hljs-string">'These are not the files you are looking for...'</span>; config.contentType.mp4 = <span class="hljs-string">'video/mp4'</span>; config.port = <span class="hljs-number">8005</span>; config.verbose = <span class="hljs-literal">true</span>; config.root = <span class="hljs-string">'~/myApp/'</span> server.deploy(config); </code></pre> <p>for https :</p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config=<span class="hljs-keyword">new</span> server.Config; config.errors[<span class="hljs-string">'404'</span>] = <span class="hljs-string">'These are not the files you are looking for...'</span>; config.contentType.mp4 = <span class="hljs-string">'video/mp4'</span>; config.port = <span class="hljs-number">8005</span>; config.verbose = <span class="hljs-literal">true</span>; config.root = <span class="hljs-string">'~/myApp/'</span> config.https.privateKey = <span class="hljs-string">`/path/to/your/certs/private/server.key`</span>; config.https.certificate= <span class="hljs-string">`/path/to/your/certs/server.pub`</span>; config.https.port = <span class="hljs-number">4433</span>; config.https.only = <span class="hljs-literal">true</span>; server.deploy(config); </code></pre> <hr> <h2 id="multiple-domains-or-subdomains">Multiple domains or subdomains</h2> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config={ <span class="hljs-attr">port</span>:<span class="hljs-number">8010</span>, <span class="hljs-attr">root</span>:__dirname + <span class="hljs-string">'/www/myApp/'</span>, <span class="hljs-attr">domain</span>:<span class="hljs-string">'myapp.com'</span>, <span class="hljs-attr">domains</span>:{ <span class="hljs-string">'a.myapp.com'</span>:__dirname+<span class="hljs-string">'/www/a-myApp/'</span>, <span class="hljs-string">'yourapp.com'</span>:__dirname+<span class="hljs-string">'/someFolder/yourApp/'</span> } } server.deploy(config); </code></pre> <h2 id="-config-class-http-riaevangelist-github-io-node-http-server-server-config-js-html-"><a href="http://riaevangelist.github.io/node-http-server/server/Config.js.html">Config Class</a></h2> <h3 id="default-node-http-server-configuration">Default node HTTP server configuration</h3> <p>All of these can be modified and passed into <code>new server.Server(myConfigs)</code> or <code>server.deploy(myConfigs)</code></p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> myConfig=<span class="hljs-keyword">new</span> server.Config; myConfig.verbose=<span class="hljs-literal">true</span>; myConfig.port=<span class="hljs-number">9922</span>; <span class="hljs-keyword">const</span> myServer=<span class="hljs-keyword">new</span> server.Server(config); myServer.deploy(); <span class="hljs-comment">//or more basically</span> server.deploy({<span class="hljs-attr">port</span>:<span class="hljs-number">9922</span>,<span class="hljs-attr">verbose</span>:<span class="hljs-literal">true</span>}); </code></pre> <h4 id="defaults-description">defaults description</h4> <pre><code class="lang-javascript"> { <span class="hljs-attr">verbose</span> : (args.verbose==<span class="hljs-string">'true'</span>)||<span class="hljs-literal">false</span>, <span class="hljs-attr">port</span> : args.port||defaults.port, <span class="hljs-attr">root</span> : args.root||defaults.root, <span class="hljs-attr">domain</span> : args.domain||defaults.domain, <span class="hljs-attr">https</span> :{ <span class="hljs-attr">ca</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">privateKey</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">certificate</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">port</span>:<span class="hljs-number">443</span>, <span class="hljs-attr">only</span>:<span class="hljs-literal">false</span> }, <span class="hljs-attr">log</span> : <span class="hljs-literal">false</span>, <span class="hljs-attr">logFunction</span> : serverLogging, <span class="hljs-attr">domains</span> : { <span class="hljs-comment">/*******************\ * domain : /that/domains/root/dir * * for sub domains, specify the whole host i.e. "my.sub.domain" * you may need to edit your hosts file, cnames or iptable * domain or my.domain etc. goes to 127.0.0.1 for local development * *****************/</span> }, <span class="hljs-attr">server</span> : { <span class="hljs-attr">index</span> : args.index||defaults.index, <span class="hljs-attr">noCache</span> : args.noCache==<span class="hljs-string">'false'</span> ? <span class="hljs-literal">false</span> : <span class="hljs-literal">true</span>, <span class="hljs-attr">timeout</span> : <span class="hljs-number">30000</span> <span class="hljs-comment">//30 second timeout</span> }, <span class="hljs-attr">contentType</span> : { <span class="hljs-attr">html</span> : <span class="hljs-string">'text/html'</span>, <span class="hljs-attr">css</span> : <span class="hljs-string">'text/css'</span>, <span class="hljs-attr">js</span> : <span class="hljs-string">'text/javascript'</span>, <span class="hljs-attr">json</span> : <span class="hljs-string">'application/json'</span>, <span class="hljs-attr">txt</span> : <span class="hljs-string">'text/plain'</span>, <span class="hljs-attr">jpeg</span> : <span class="hljs-string">'image/jpeg'</span>, <span class="hljs-attr">jpg</span> : <span class="hljs-string">'image/jpeg'</span>, <span class="hljs-attr">png</span> : <span class="hljs-string">'image/png'</span>, <span class="hljs-attr">gif</span> : <span class="hljs-string">'image/gif'</span>, <span class="hljs-attr">ico</span> : <span class="hljs-string">'image/x-icon'</span>, <span class="hljs-attr">appcache</span>: <span class="hljs-string">'text/cache-manifest'</span> }, <span class="hljs-attr">restrictedType</span>: { }, <span class="hljs-attr">errors</span>:{ <span class="hljs-attr">headers</span> : { <span class="hljs-string">'Content-Type'</span> : <span class="hljs-string">'text/plain'</span> }, <span class="hljs-number">404</span>: <span class="hljs-string">'404 MIA'</span>, <span class="hljs-number">415</span>: <span class="hljs-string">'415 File type not supported'</span>, <span class="hljs-number">403</span>: <span class="hljs-string">'403 Access Denied'</span>, <span class="hljs-number">500</span>: <span class="hljs-string">'500 {{err}}'</span> } }; </code></pre> <table> <thead> <tr> <th>key</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>verbose</td> <td>display detailed info about what server is doing via terminal.</td> </tr> <tr> <td>port</td> <td>the port on which the server should run</td> </tr> <tr> <td>root</td> <td>the absolute path to the root dir for the domain</td> </tr> <tr> <td>domain</td> <td>the server domain. To accept incoming requests for <strong><em>ANY Applicable Domain</em></strong> use <code>0.0.0.0</code> this will allow any request that is pointed at this machine on the specified port to use this server config.</td> </tr> <tr> <td>https</td> <td>settings for https, these wil only take effect if both a <code>privateKey</code> and a <code>certificate</code> are specified. Setting <code>only</code> to be true means the instance will only serve over https</td> </tr> <tr> <td>https.privateKey</td> <td>path to your servers private key like ./local-certs/private/server.key or similar</td> </tr> <tr> <td>https.certificate</td> <td>path to your servers public cert like ./local-certs/client.pub or similar</td> </tr> <tr> <td>https.ca</td> <td>path to your officially signed CA’s certificate authority file servers public cert like ./local-certs/ca-bundle.crt or similar. This is often needed for officially signed and generated certs, but not for self signed certs so it is optional.</td> </tr> <tr> <td>log</td> <td>full path to log file, if specified and the file is not present, it will be created, however the dir must be there. Example path : <code>/tmp/server.log</code> It is recommended that you timestamp this file name with a time stamp like : <code>&#39;~/serverLogs/domain-&#39;+new Date().getTime()+&#39;.log&#39;</code> this will create a new log file each time the server is started/restarted/reboot etc…</td> </tr> <tr> <td>logFunction</td> <td>the default function appends timestamps to the headers object and logs as JSON in the <code>log</code> file. You can assign your own function here as well. It should accepts a javascript Object as the first argument.</td> </tr> <tr> <td>domains.*</td> <td>this is a mapping of hostname to path. It can be used for multiple different domains, or for subdomains.</td> </tr> <tr> <td>server.index</td> <td>the default file to look for in a dir. if not found a <strong>404</strong> will be displayed</td> </tr> <tr> <td>server.noCache</td> <td>should the server prevent caching</td> </tr> <tr> <td>server.timeout</td> <td>the amount of time allowed for no activity on a connection before it is closed.</td> </tr> <tr> <td>contentType.*</td> <td>mapping of file extension to header Content-Type value.</td> </tr> <tr> <td>restrictedType.*</td> <td>extensions to which access will be denied.</td> </tr> <tr> <td>errors.headers</td> <td>these are the headers that will automatically be applied to all error responses. You can add custom headers per error in the <code>beforeServe</code> function</td> </tr> <tr> <td>errors.*</td> <td>error headers and error strings, these can be anything you like from html to text etc. The <strong>500</strong> error will replace <code>{{err}}</code> in the specified value with the actual error message from the server.</td> </tr> </tbody> </table> <h4 id="config-domains-">config.domains.*</h4> <p>Use this object for sub domains, or hosting multiple domains on the same port. Specify the whole host i.e. “my.sub.domain.com” or “amazing-domain.com”.</p> <p>You may need to edit your hosts file, cnames, iptable to get this to work on your server or development environment.</p> <p>You can add the below example to your hosts file to run some of the examples from the <code>/example/basic</code> directory which use multiple domains on occasion.</p> <pre><code><span class="hljs-section">#node-http-server examples</span> 127.0.0.1 myapp 127.0.0.1 a.myapp 127.0.0.1 yourapp.com </code></pre><pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>); <span class="hljs-keyword">const</span> config={ <span class="hljs-attr">port</span>:<span class="hljs-number">8000</span>, <span class="hljs-attr">root</span>:__dirna\me+<span class="hljs-string">'/appRoot/'</span>, <span class="hljs-attr">domain</span>:<span class="hljs-string">'myapp'</span>, <span class="hljs-attr">domains</span>:{ <span class="hljs-comment">//subdomain</span> <span class="hljs-string">'a.myapp'</span>:<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/appSubDomainRoot/`</span>, <span class="hljs-comment">//totally different domain, but also on port 8000</span> <span class="hljs-string">'yourapp.com'</span>:<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/appOtherDomainRoot/`</span> } } server.deploy(config); </code></pre> <hr> <h2 id="extending-the-server">Extending the Server</h2> <p>If you wish to make a reusable Server Class of your own to share or for some internal use you can always extend the server class and make your own module too.</p> <pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> os=<span class="hljs-built_in">require</span>(<span class="hljs-string">'os'</span>); <span class="hljs-keyword">const</span> Server=<span class="hljs-built_in">require</span>(<span class="hljs-string">'node-http-server'</span>).Server; <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyAwesomeServer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Server</span>()</span>{ <span class="hljs-keyword">constructor</span>(){ <span class="hljs-keyword">super</span>(); } IP(){ <span class="hljs-keyword">const</span> networkInterfaces = os.networkInterfaces(); <span class="hljs-keyword">const</span> serverIPs={}; <span class="hljs-keyword">const</span> interfaceKeys=<span class="hljs-built_in">Object</span>.keys(networkInterfaces); <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i <span class="hljs-keyword">in</span> interfaceKeys){ serverIPs[ interfaceKeys[i] ]={}; <span class="hljs-keyword">const</span> interface=networkInterfaces[ interfaceKeys[i] ]; <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> j <span class="hljs-keyword">in</span> interface){ serverIPs[ interfaceKeys[i] ][ interface[j].family ]=interface[j].address; } } <span class="hljs-keyword">return</span> se