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.

1,041 lines (871 loc) 48.6 kB
<!DOCTYPE html> <html> <head> <title>Server</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":false}},{"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":"."},"state":{"opened":true}},{"id":"./server/Config.js","text":"Config.js","icon":"jstree-file","parent":"./server","a_attr":{"href":"Config.js.html"},"state":{"selected":false}},{"id":"./server/Server.js","text":"Server.js","icon":"jstree-file","parent":"./server","a_attr":{"href":"Server.js.html"},"state":{"selected":true}},{"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> Server </h1> <div class="subHeading"> ./server/Server.js </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 "> <li id="section-1"> <div class="annotation"> </div><div class="content"> <div class="highlight"><pre><span class="hljs-meta">'use strict'</span>; <span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>), https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>), url = <span class="hljs-built_in">require</span>(<span class="hljs-string">'url'</span>), path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>), fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>), querystring=<span class="hljs-built_in">require</span>(<span class="hljs-string">'querystring'</span>), Config = <span class="hljs-built_in">require</span>(<span class="hljs-string">`<span class="hljs-subst">${__dirname}</span>/Config.js`</span>);</pre></div> </div> </li> <li id="section-2"> <div class="annotation"> <h1 id="-server-class-https-github-com-riaevangelist-node-http-server-server-class-"><a href="https://github.com/RIAEvangelist/node-http-server#server-class">SERVER CLASS</a></h1> <hr> <p> You can pass a <code>userConfig</code> object to shallow merge and/or decorate the <code>server.config</code> when instatiating if you desire.</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-comment">// server is a Server instation already so to modify or decorate its config, you</span> <span class="hljs-comment">// must call the server.deploy method.</span> server.deploy({<span class="hljs-attr">verbose</span>:<span class="hljs-literal">true</span>}) <span class="hljs-keyword">const</span> Server=server.Server; <span class="hljs-comment">// Server is a refrence to the Server class so you can extend or instatiate it.</span> <span class="hljs-keyword">const</span> myServer=<span class="hljs-keyword">new</span> Server({<span class="hljs-attr">verbose</span>:<span class="hljs-literal">true</span>}); <span class="hljs-comment">// this is the instatiated server which now contains your desired defaults.</span> <span class="hljs-comment">// like the first example, it too can still be modified on deployment</span> myServer.deploy({<span class="hljs-attr">port</span>:<span class="hljs-number">8888</span>},(server)=&gt;{<span class="hljs-built_in">console</span>.log(server)}); </code></pre> </div><div class="content"> <div class="highlight"><pre> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Server</span></span>{</pre></div> </div> </li> <li id="section-3"> <div class="annotation"> <p> <code>server.config</code> is where the servers configuration will reside. It is a new instance of the <a href="http://riaevangelist.github.io/node-http-server/server/Config.js.html">Config class</a> which will be shallow merged and/or decorated by with the passed <code>userConfig</code> if one is passed upon construction of the Server class, or to the <code>server.deploy</code> method.</p> <p> <a href="https://github.com/RIAEvangelist/node-http-server#custom-configuration">Detailed info on the server.config or userConfig</a></p> </div><div class="content"> <div class="highlight"><pre> <span class="hljs-keyword">constructor</span>(userConfig){ <span class="hljs-keyword">this</span>.config=<span class="hljs-keyword">new</span> <span class="hljs-keyword">this</span>.Config(userConfig); }</pre></div> </div> </li> <li id="section-4"> <div class="annotation"> <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/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> <p> See the example folder for more detailed examples, or check the node-http-server readme for some <a href="https://github.com/RIAEvangelist/node-http-server#examples">Quickstart Examples for deploying a node server</a></p> </div><div class="content"> <div class="highlight"><pre> get deploy(){ <span class="hljs-keyword">return</span> deploy; }</pre></div> </div> </li> <li id="section-5"> <div class="annotation"> <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> </div><div class="content"> <div class="highlight"><pre> onRawRequest(request,response,serve){ }</pre></div> </div> </li> <li id="section-6"> <div class="annotation"> <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>raw 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> </div><div class="content"> <div class="highlight"><pre> onRequest(request,response,serve){ }</pre></div> </div> </li> <li id="section-7"> <div class="annotation"> <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>decorated 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> <code>type 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> </div><div class="content"> <div class="highlight"><pre> beforeServe(request,response,body,encoding,serve){ }</pre></div> </div> </li> <li id="section-8"> <div class="annotation"> <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> </div><div class="content"> <div class="highlight"><pre> afterServe(request){ } get serve(){ <span class="hljs-keyword">return</span> serve; } get serveFile(){ <span class="hljs-keyword">return</span> serveFile; } get Config(){ <span class="hljs-keyword">return</span> Config } get Server(){ <span class="hljs-keyword">return</span> Server } } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deploy</span>(<span class="hljs-params">userConfig, readyCallback=function(</span>)</span>{}){ <span class="hljs-built_in">Object</span>.defineProperty( <span class="hljs-keyword">this</span>, <span class="hljs-string">'server'</span>, { <span class="hljs-attr">value</span>:http.createServer( requestRecieved.bind(<span class="hljs-keyword">this</span>) ), <span class="hljs-attr">writable</span>:<span class="hljs-literal">false</span>, <span class="hljs-attr">enumerable</span>:<span class="hljs-literal">true</span> } ); <span class="hljs-keyword">if</span>(userConfig){ <span class="hljs-built_in">Object</span>.assign(<span class="hljs-keyword">this</span>.config,userConfig); } <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.https &amp;&amp; <span class="hljs-keyword">this</span>.config.https.privateKey &amp;&amp; <span class="hljs-keyword">this</span>.config.https.certificate){ <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.config.https.port){ <span class="hljs-keyword">this</span>.config.https.port=<span class="hljs-number">443</span>; } <span class="hljs-keyword">this</span>.config.httpsOptions = { <span class="hljs-attr">key</span>: fs.readFileSync(<span class="hljs-keyword">this</span>.config.https.privateKey), <span class="hljs-attr">cert</span>: fs.readFileSync(<span class="hljs-keyword">this</span>.config.https.certificate), <span class="hljs-attr">passphrase</span>: <span class="hljs-keyword">this</span>.config.https.passphrase }; <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.https.ca){ <span class="hljs-keyword">this</span>.config.httpsOptions.ca=fs.readFileSync(<span class="hljs-keyword">this</span>.config.https.ca); } <span class="hljs-built_in">Object</span>.defineProperty( <span class="hljs-keyword">this</span>, <span class="hljs-string">'secureServer'</span>, { <span class="hljs-attr">value</span>:https.createServer( <span class="hljs-keyword">this</span>.config.httpsOptions, requestRecieved.bind(<span class="hljs-keyword">this</span>) ), <span class="hljs-attr">writable</span>:<span class="hljs-literal">false</span>, <span class="hljs-attr">enumerable</span>:<span class="hljs-literal">true</span> } ); }<span class="hljs-keyword">else</span>{ <span class="hljs-keyword">this</span>.config.https={ <span class="hljs-attr">only</span>:<span class="hljs-literal">false</span> }; } <span class="hljs-keyword">this</span>.config.logID=<span class="hljs-string">`### <span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.domain}</span> server`</span>; <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log( <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> configured with ###\n\n`</span>,<span class="hljs-keyword">this</span>.config); } <span class="hljs-keyword">this</span>.server.timeout=<span class="hljs-keyword">this</span>.config.server.timeout; <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.config.https.only){ <span class="hljs-keyword">this</span>.server.listen( <span class="hljs-keyword">this</span>.config.port, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> listening on port <span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.port}</span> ###\n\n`</span>); }</pre></div> </div> </li> <li id="section-9"> <div class="annotation"> <p>The <code>readyCallback</code> is passed the full server instance so that you may use the same callback to handle multiple server instances in the same code instead of writing an inline callback… think about it ;)</p> </div><div class="content"> <div class="highlight"><pre> readyCallback(<span class="hljs-keyword">this</span>); }.bind(<span class="hljs-keyword">this</span>) ); } <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.httpsOptions){ <span class="hljs-keyword">this</span>.secureServer.listen( <span class="hljs-keyword">this</span>.config.https.port, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`HTTPS: <span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> listening on port <span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.https.port}</span> ###\n\n`</span>); }</pre></div> </div> </li> <li id="section-10"> <div class="annotation"> <p> for example the same ready callback could handle both the https and http servers with a simple test for the servers port</p> </div><div class="content"> <div class="highlight"><pre> readyCallback(<span class="hljs-keyword">this</span>); }.bind(<span class="hljs-keyword">this</span>) ); } } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setHeaders</span>(<span class="hljs-params">response,headers</span>)</span>{ <span class="hljs-keyword">const</span> keys=<span class="hljs-built_in">Object</span>.keys(headers); <span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> i <span class="hljs-keyword">in</span> keys){ response.setHeader( keys[i], headers[keys[i]] ); } } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serveFile</span>(<span class="hljs-params">filename,exists,request,response</span>) </span>{ <span class="hljs-keyword">if</span>(!exists) { <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> 404 ###\n\n`</span>); } <span class="hljs-keyword">if</span>(!response){ <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; } response.statusCode=<span class="hljs-number">404</span>; setHeaders(response, <span class="hljs-keyword">this</span>.config.errors.headers); <span class="hljs-keyword">this</span>.serve( request, response, <span class="hljs-keyword">this</span>.config.errors[<span class="hljs-string">'404'</span>] ); <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">const</span> contentType = path.extname(filename).slice(<span class="hljs-number">1</span>); <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.config.contentType[contentType]){ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> 415 ###\n\n`</span>); } response.statusCode=<span class="hljs-number">415</span>; setHeaders(response, <span class="hljs-keyword">this</span>.config.errors.headers); <span class="hljs-keyword">this</span>.serve( request, response, <span class="hljs-keyword">this</span>.config.errors[<span class="hljs-string">'415'</span>] ); <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">if</span> ( fs.statSync(filename).isDirectory() ){ filename+=<span class="hljs-string">`/<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.server.index}</span>`</span>; } <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.config.restrictedType[contentType] ){ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> 403 ###\n\n`</span>); } response.statusCode=<span class="hljs-number">403</span>; setHeaders(response, <span class="hljs-keyword">this</span>.config.errors.headers); <span class="hljs-keyword">this</span>.serve( request, response, <span class="hljs-keyword">this</span>.config.errors[<span class="hljs-string">'403'</span>] ); <span class="hljs-keyword">return</span>; } fs.readFile( filename, <span class="hljs-string">'binary'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, file</span>) </span>{ <span class="hljs-keyword">if</span>(err) { <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> 500 ###\n\n`</span>,err,<span class="hljs-string">'\n\n'</span>); } response.statusCode=<span class="hljs-number">500</span>; setHeaders(response, <span class="hljs-keyword">this</span>.config.errors.headers); <span class="hljs-keyword">this</span>.serve( request, response, <span class="hljs-keyword">this</span>.config.errors[<span class="hljs-string">'500'</span>].replace(<span class="hljs-regexp">/\{\{err\}\}/g</span>,err) ); <span class="hljs-keyword">return</span>; } response.setHeader( <span class="hljs-string">'Content-Type'</span>, <span class="hljs-keyword">this</span>.config.contentType[contentType] ); <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.server.noCache){ response.setHeader( <span class="hljs-string">'Cache-Control'</span>, <span class="hljs-string">'no-cache, no-store, must-revalidate'</span> ); } response.statusCode=<span class="hljs-number">200</span>; <span class="hljs-keyword">this</span>.serve( request, response, file, <span class="hljs-string">'binary'</span> ); <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> 200 ###\n\n`</span>); } <span class="hljs-keyword">return</span>; }.bind(<span class="hljs-keyword">this</span>) ); } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serve</span>(<span class="hljs-params">request,response,body,encoding</span>)</span>{ <span class="hljs-keyword">if</span>(!response.statusCode){ response.statusCode=<span class="hljs-number">200</span>; } <span class="hljs-keyword">if</span>(!response.getHeader(<span class="hljs-string">'Content-Type'</span>)){ response.setHeader( <span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'text/plain'</span> ); <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> response content-type header not specified ###\n\nContent-Type set to: text/plain\n\n`</span>); } } <span class="hljs-keyword">if</span>(!encoding){ encoding=<span class="hljs-string">'utf8'</span>; <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> encoding not specified ###\nencoding set to:\n`</span>,encoding,<span class="hljs-string">'\n\n'</span>); } } <span class="hljs-keyword">const</span> refBody=<span class="hljs-keyword">new</span> RefString; <span class="hljs-keyword">const</span> refEncoding=<span class="hljs-keyword">new</span> RefString; refBody.value=body; refEncoding.value=encoding;</pre></div> </div> </li> <li id="section-11"> <div class="annotation"> <p>return any value to force or specify delayed or manual serving</p> </div><div class="content"> <div class="highlight"><pre> <span class="hljs-keyword">if</span>( <span class="hljs-keyword">this</span>.beforeServe( request, response, refBody, refEncoding, completeServing.bind(<span class="hljs-keyword">this</span>) ) ){ <span class="hljs-keyword">return</span>; }; completeServing.bind(<span class="hljs-keyword">this</span>)(request,response,refBody,encoding); <span class="hljs-keyword">return</span>; } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">completeServing</span>(<span class="hljs-params">request,response,refBody,refEncoding</span>)</span>{ <span class="hljs-keyword">if</span>(!(refBody <span class="hljs-keyword">instanceof</span> RefString)){ refBody=<span class="hljs-keyword">new</span> RefString(refBody); } <span class="hljs-keyword">if</span>(!(refEncoding <span class="hljs-keyword">instanceof</span> RefString)){ refEncoding=<span class="hljs-keyword">new</span> RefString(refEncoding||<span class="hljs-string">'binary'</span>); } <span class="hljs-keyword">if</span>(response.finished){ <span class="hljs-keyword">this</span>.afterServe(request); <span class="hljs-keyword">return</span>; } response.end( refBody.value, refEncoding.value, <span class="hljs-keyword">this</span>.afterServe.bind(<span class="hljs-keyword">this</span>,request) ); } <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RefString</span></span>{ <span class="hljs-keyword">constructor</span>(value){ <span class="hljs-keyword">if</span>(value){ <span class="hljs-keyword">this</span>._string=value; } } get value(){ <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._string; } set value(value){ <span class="hljs-keyword">this</span>._string=value; <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._string; } } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">requestRecieved</span>(<span class="hljs-params">request,response</span>)</span>{ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.log){ <span class="hljs-keyword">const</span> logData={ <span class="hljs-attr">method</span> : request.method, <span class="hljs-attr">url</span> : request.url, <span class="hljs-attr">headers</span> : request.headers }; <span class="hljs-keyword">this</span>.config.logFunction( logData ); } <span class="hljs-keyword">let</span> uri = url.parse(request.url); uri.protocol=<span class="hljs-string">'http'</span>; uri.host=uri.hostname=request.headers.host; uri.port=<span class="hljs-number">80</span>; uri.query=querystring.parse(uri.query); <span class="hljs-keyword">if</span>(request.connection.encrypted){ uri.protocol=<span class="hljs-string">'https'</span>; uri.port=<span class="hljs-number">443</span>; } ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{ <span class="hljs-keyword">if</span>(!uri.host){ <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">const</span> host=uri.host.split(<span class="hljs-string">':'</span>); <span class="hljs-keyword">if</span>(!host[<span class="hljs-number">1</span>]){ <span class="hljs-keyword">return</span>; } uri.host=uri.hostname=host[<span class="hljs-number">0</span>]; uri.port=host[<span class="hljs-number">1</span>]; } )(); <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> key <span class="hljs-keyword">in</span> uri){ <span class="hljs-keyword">if</span>(uri[key]!==<span class="hljs-literal">null</span>){ <span class="hljs-keyword">continue</span>; } uri[key]=<span class="hljs-string">''</span>; } request.uri=uri; <span class="hljs-keyword">if</span>( <span class="hljs-keyword">this</span>.onRawRequest( request, response, completeServing.bind(<span class="hljs-keyword">this</span>) ) ){ <span class="hljs-keyword">return</span>; }; uri=uri.pathname; <span class="hljs-keyword">if</span> (uri==<span class="hljs-string">'/'</span>){ uri=<span class="hljs-string">`/<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.server.index}</span>`</span>; } <span class="hljs-keyword">let</span> hostname= []; <span class="hljs-keyword">if</span> (request.headers.host !== <span class="hljs-literal">undefined</span>){ hostname = request.headers.host.split(<span class="hljs-string">':'</span>); } <span class="hljs-keyword">let</span> root = <span class="hljs-keyword">this</span>.config.root; <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> REQUEST ###\n\n`</span>, request.headers,<span class="hljs-string">'\n'</span>, uri,<span class="hljs-string">'\n\n'</span>, hostname,<span class="hljs-string">'\n\n'</span> ); } <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.domain!=<span class="hljs-string">'0.0.0.0'</span> &amp;&amp; hostname.length &gt; <span class="hljs-number">0</span> &amp;&amp; hostname[<span class="hljs-number">0</span>]!=<span class="hljs-keyword">this</span>.config.domain){ <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">this</span>.config.domains[hostname[<span class="hljs-number">0</span>]]){ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> INVALID HOST ###\n\n`</span>); } <span class="hljs-keyword">this</span>.serveFile(hostname[<span class="hljs-number">0</span>],<span class="hljs-literal">false</span>,response); <span class="hljs-keyword">return</span>; } root=<span class="hljs-keyword">this</span>.config.domains[hostname[<span class="hljs-number">0</span>]]; } <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">this</span>.config.logID}</span> USING ROOT : <span class="hljs-subst">${root}</span>###\n\n`</span>); } <span class="hljs-keyword">if</span>(uri.slice(<span class="hljs-number">-1</span>)==<span class="hljs-string">'/'</span>){ uri+=<span class="hljs-keyword">this</span>.config.server.index; } request.url=uri; request.serverRoot=root; request.body=<span class="hljs-string">''</span>; request.on( <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">chunk</span>)</span>{ request.body+=chunk; }.bind(<span class="hljs-keyword">this</span>) ).on( <span class="hljs-string">'end'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.config.verbose){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`###REQUEST BODY : <span class="hljs-subst">${request.body}</span> ### `</span>); } requestBodyComplete.bind(<span class="hljs-keyword">this</span>,request,response)(); }.bind(<span class="hljs-keyword">this</span>) ); } <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">requestBodyComplete</span>(<span class="hljs-params">request,response</span>)</span>{</pre></div> </div> </li> <li id="section-12"> <div class="annotation"> <p>return any value to force or specify delayed or manual serving</p> </div><div class="content"> <div class="highlight"><pre> <span class="hljs-keyword">if</span>( <span class="hljs-keyword">this</span>.onRequest( request, response, completeServing.bind(<span class="hljs-keyword">this</span>) ) ){ <span class="hljs-keyword">return</span>; }; <span class="hljs-keyword">const</span> filename = path.join( request.serverRoot, request.url ); fs.exists( filename, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fileExists</span>(<span class="hljs-params">exists</span>)</span>{ <span class="hljs-keyword">this</span>.serveFile(filename,exists,request,response); }.bind(<span class="hljs-keyword">this</span>) ); } <span class="hljs-built_in">module</span>.exports=<span class="hljs-keyword">new</span> Server;</pre></div> </div> </li> </ul> </section> </body> </html>