Click here to Skip to main content
15,891,873 members
Articles / Web Development / Node.js

Node.Js And Stuff

Rate me:
Please Sign up or sign in to vote.
4.97/5 (55 votes)
11 Feb 2013CPOL23 min read 359.7K   2.3K   172  
Small demo app using Node.Js/Socket.IO/MongoDB/D3.Js and jQuery.
<html>
	<head>
		<title>FlashPolicyFileServer</title>
		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
		<style>body {
    margin: 0;
    padding: 0;
    font: 14px/1.5 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
    color: #252519;
}
a {
    color: #252519;
}
a:hover {
    text-decoration: underline;
    color: #19469D;
}
p {
    margin: 12px 0;
}
h1, h2, h3 {
    margin: 0;
    padding: 0;
}
table#source {
    width: 100%;
    border-collapse: collapse;
}
table#source td:first-child {
    padding: 30px 40px 30px 40px;
    vertical-align: top;
}
table#source td:first-child,
table#source td:first-child pre {
    width: 450px;
}
table#source td:last-child {
    padding: 30px 0 30px 40px;
    border-left: 1px solid #E5E5EE;
    background: #F5F5FF;
}
table#source tr {
    border-bottom: 1px solid #E5E5EE;
}
table#source tr.filename {
    padding-top: 40px;
    border-top: 1px solid #E5E5EE;
}
table#source tr.filename td:first-child {
    text-transform: capitalize;
}
table#source tr.filename td:last-child {
    font-size: 12px;
}
table#source tr.filename h2 {
    margin: 0;
    padding: 0;
    cursor: pointer;
}
table#source tr.code h1,
table#source tr.code h2,
table#source tr.code h3 {
    margin-top: 30px;
    font-family: "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
    font-size: 18px;
}
table#source tr.code h2 {
    font-size: 16px;
}
table#source tr.code h3 {
    font-size: 14px;
}
table#source tr.code ul {
    margin: 15px 0 15px 35px;
    padding: 0;
}
table#source tr.code ul li {
    margin: 0;
    padding: 1px 0;
}
table#source tr.code ul li p {
    margin: 0;
    padding: 0;
}
table#source tr.code td:first-child pre {
    padding: 20px;
}
#ribbon {
    position: fixed;
    top: 0;
    right: 0;
}
code .string { color: #219161; }
code .regexp { color: #219161; }
code .keyword { color: #954121; }
code .number { color: #19469D; }
code .comment { color: #bbb; }
code .this { color: #19469D; }</style>
		<script>
			$(function(){
				$('tr.code').hide();
				$('tr.filename').toggle(function(){
					$(this).nextUntil('.filename').fadeIn();
				}, function(){
					$(this).nextUntil('.filename').fadeOut();
				});
			});
		</script>
	</head>
	<body>
<table id="source"><tbody><tr><td><h1>FlashPolicyFileServer</h1></td><td></td></tr><tr class="filename"><td><h2 id="lib/server.js"><a href="#">server</a></h2></td><td>lib/server.js</td></tr><tr class="code">
<td class="docs">
<p>Module dependencies and cached references.
 </p>
</td>
<td class="code">
<pre><code><span class="keyword">var</span> <span class="variable">slice</span> = <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">slice</span>
  , <span class="variable">net</span> = <span class="variable">require</span>(<span class="string">'net'</span>);</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>The server that does the Policy File severing</p>

<h2>Options</h2>

<ul><li><code>log</code>  false or a function that can output log information, defaults to console.log?</li></ul>

<h2></h2>

<ul><li><p><strong>param</strong>: <em>Object</em>  options Options to customize the servers functionality.</p></li><li><p><strong>param</strong>: <em>Array</em>  origins The origins that are allowed on this server, defaults to <code>*:*</code>.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="keyword">function</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
  <span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>;
  
  <span class="this">this</span>.<span class="variable">origins</span> = <span class="variable">origins</span> || [<span class="string">'*:*'</span>];
  <span class="this">this</span>.<span class="variable">port</span> = <span class="number integer">843</span>;
  <span class="this">this</span>.<span class="variable">log</span> = <span class="variable">console</span>.<span class="variable">log</span>;
  
  <span class="comment">// merge `this` with the options</span>
  <span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">options</span>).<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">key</span>){
    <span class="variable">me</span>[<span class="variable">key</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">me</span>[<span class="variable">key</span>] = <span class="variable">options</span>[<span class="variable">key</span>])
  });
  
  <span class="comment">// create the net server</span>
  <span class="this">this</span>.<span class="variable">socket</span> = <span class="variable">net</span>.<span class="variable">createServer</span>(<span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">socket</span>){
    <span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">socketError</span>(){ <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>) });
    <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>);
  });
  
  <span class="comment">// Listen for errors as the port might be blocked because we do not have root priv.</span>
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">serverError</span>(<span class="variable">err</span>){
    <span class="comment">// Special and common case error handling</span>
    <span class="keyword">if</span> (<span class="variable">err</span>.<span class="variable">errno</span> == <span class="number integer">13</span>){
      <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(
        <span class="string">'Unable to listen to port `'</span> + <span class="variable">me</span>.<span class="variable">port</span> + <span class="string">'` as your Node.js instance does not have root privileges. '</span> +
        (
          <span class="variable">me</span>.<span class="variable">server</span>
          ? <span class="string">'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'</span>
          : <span class="string">'No fallback server supplied.'</span>
        )
      );
      
      <span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
      <span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">socket</span>;

      <span class="variable">me</span>.<span class="variable">emit</span>(<span class="string">'connect_failed'</span>, <span class="variable">err</span>);
    } <span class="keyword">else</span> {
      <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'FlashPolicyFileServer received a error event:\n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
    }
  });
  
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'timeout'</span>, <span class="keyword">function</span> <span class="variable">serverTimeout</span>(){});
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'close'</span>, <span class="keyword">function</span> <span class="variable">serverClosed</span>(<span class="variable">err</span>){
    <span class="variable">err</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Server closing due to an error: \n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
    
    <span class="keyword">if</span> (<span class="variable">me</span>.<span class="variable">server</span>){
      <span class="comment">// not online anymore</span>
      <span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>;
      
      <span class="comment">// Remove the inline policy listener if we close down</span>
      <span class="comment">// but only when the server was `online` (see listen prototype)</span>
      <span class="keyword">if</span>( <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>){
        <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">removeListener</span>(<span class="string">'connection'</span>, <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
      }
    }
    <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Shutting down FlashPolicyFileServer'</span>);
  });
  
  <span class="comment">// Compile the initial `buffer`</span>
  <span class="this">this</span>.<span class="variable">compile</span>();
}</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Start listening for requests</p>

<h2></h2>

<ul><li><p><strong>param</strong>: <em>Number</em>  port The port number it should be listening to.</p></li><li><p><strong>param</strong>: <em>Server</em>  server A HTTP server instance, this will be used to listen for inline requests</p></li><li><p><strong>param</strong>: <em>Function</em>  cb The callback needs to be called once server is ready</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">listen</span> = <span class="keyword">function</span> <span class="variable">listen</span>(<span class="variable">port</span>, <span class="variable">server</span>, <span class="variable">cb</span>){
  <span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>
    , <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
    , <span class="variable">callback</span>;
  
  <span class="comment">// assign the correct vars, for flexible arguments</span>
  <span class="variable">args</span>.<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">args</span>(<span class="variable">arg</span>){
    <span class="keyword">var</span> <span class="variable">type</span> = <span class="keyword">typeof</span> <span class="variable">arg</span>;
    
    <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'number'</span>) <span class="variable">me</span>.<span class="variable">port</span> = <span class="variable">arg</span>;
    <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'function'</span>) <span class="variable">callback</span> = <span class="variable">arg</span>;
    <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'object'</span>) <span class="variable">me</span>.<span class="variable">server</span> = <span class="variable">arg</span>;
  });
  
  <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">server</span>){
    
    <span class="comment">// no one in their right mind would ever create a `@` prototype, so Im just gonna store</span>
    <span class="comment">// my function on the server, so I can remove it later again once the server(s) closes</span>
    <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>] = <span class="keyword">function</span> <span class="variable">connection</span>(<span class="variable">socket</span>){
      <span class="variable">socket</span>.<span class="variable">once</span>(<span class="string">'data'</span>, <span class="keyword">function</span> <span class="variable">requestData</span>(<span class="variable">data</span>){
        <span class="comment">// if it's a Flash policy request, and we can write to the </span>
        <span class="keyword">if</span> (
             <span class="variable">data</span>
          &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>[<span class="number integer">0</span>] === <span class="number integer">60</span>
          &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>.<span class="variable">toString</span>() === <span class="string">'&lt;policy-file-request/&gt;\0'</span>
          &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">socket</span>
          &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'open'</span> || <span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'writeOnly'</span>)
        ){
          <span class="comment">// send the buffer</span>
          <span class="variable">socket</span>.<span class="variable">end</span>(<span class="variable">me</span>.<span class="variable">buffer</span>);
        }
      });
    };
    <span class="comment">// attach it</span>
    <span class="this">this</span>.<span class="variable">server</span>.<span class="variable">on</span>(<span class="string">'connection'</span>, <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
  }
  
  <span class="comment">// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.</span>
  <span class="comment">// this flag is needed because if a error occurs and the we cannot boot up the server the</span>
  <span class="comment">// fallback functionality should not be removed during the `close` event</span>
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">listen</span>(<span class="this">this</span>.<span class="variable">port</span>, <span class="keyword">function</span> <span class="variable">serverListening</span>(){
   <span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">online</span> = <span class="variable">true</span>;
   
   <span class="keyword">if</span> (<span class="variable">callback</span>) <span class="variable">callback</span>(), <span class="variable">callback</span> = <span class="variable">undefined</span>;
   
  });
  
  <span class="keyword">return</span> <span class="this">this</span>;
};</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Adds a new origin to the Flash Policy File.</p>

<h2></h2>

<ul><li><p><strong>param</strong>: <em>Arguments</em>  The origins that need to be added.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">add</span> = <span class="keyword">function</span> <span class="variable">add</span>(){
  <span class="keyword">var</span> <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
    , <span class="variable">i</span> = <span class="variable">args</span>.<span class="variable">length</span>;
  
  <span class="comment">// flag duplicates</span>
  <span class="keyword">while</span> (<span class="variable">i</span>--){
    <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">args</span>[<span class="variable">i</span>]) &<span class="variable">gt</span>;= <span class="number integer">0</span>){
      <span class="variable">args</span>[<span class="variable">i</span>] = <span class="keyword">null</span>;
    }
  }
  
  <span class="comment">// Add all the arguments to the array</span>
  <span class="comment">// but first we want to remove all `falsy` values from the args</span>
  <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">push</span>.<span class="variable">apply</span>(
    <span class="this">this</span>.<span class="variable">origins</span>
  , <span class="variable">args</span>.<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">value</span>){ <span class="keyword">return</span> !!<span class="variable">value</span> })
  );
  
  <span class="this">this</span>.<span class="variable">compile</span>();
  <span class="keyword">return</span> <span class="this">this</span>;
};</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Removes a origin from the Flash Policy File.</p>

<h2></h2>

<ul><li><p><strong>param</strong>: <em>String</em>  origin The origin that needs to be removed from the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">remove</span> = <span class="keyword">function</span> <span class="variable">remove</span>(<span class="variable">origin</span>){
  <span class="keyword">var</span> <span class="variable">position</span> = <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">origin</span>);
  
  <span class="comment">// only remove and recompile if we have a match</span>
  <span class="keyword">if</span> (<span class="variable">position</span> &<span class="variable">gt</span>; <span class="number integer">0</span>){
    <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">splice</span>(<span class="variable">position</span>,<span class="number integer">1</span>);
    <span class="this">this</span>.<span class="variable">compile</span>();
  }
  
  <span class="keyword">return</span> <span class="this">this</span>;
};</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Closes and cleans up the server</p>

<ul><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">close</span> = <span class="keyword">function</span> <span class="variable">close</span>(){
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
  <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">close</span>();
  
  <span class="keyword">return</span> <span class="this">this</span>;
};</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Proxy the event listener requests to the created Net server
 </p>
</td>
<td class="code">
<pre><code><span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">process</span>.<span class="class">EventEmitter</span>.<span class="variable">prototype</span>).<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">proxy</span>(<span class="variable">key</span>){
  <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] = <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] || <span class="keyword">function</span> (){
    <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">socket</span>) <span class="this">this</span>.<span class="variable">socket</span>[<span class="variable">key</span>].<span class="variable">apply</span>(<span class="this">this</span>.<span class="variable">socket</span>, <span class="variable">arguments</span>);
    <span class="keyword">return</span> <span class="this">this</span>;
  };
});</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Creates a new server instance.</p>

<h2></h2>

<ul><li><p><strong>param</strong>: <em>Object</em>  options A options object to override the default config</p></li><li><p><strong>param</strong>: <em>Array</em>  origins The origins that should be allowed by the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
</td>
<td class="code">
<pre><code><span class="variable">exports</span>.<span class="variable">createServer</span> = <span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
  <span class="variable">origins</span> = <span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">origins</span>) ? <span class="variable">origins</span> : (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) ? <span class="variable">options</span> : <span class="variable">false</span>);
  <span class="variable">options</span> = !<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">options</span> ? <span class="variable">options</span> : {};
  
  <span class="keyword">return</span> <span class="keyword">new</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>);
};</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Provide a hook to the original server, so it can be extended if needed.
 </p>
</td>
<td class="code">
<pre><code><span class="variable">exports</span>.<span class="class">Server</span> = <span class="class">Server</span>;</code></pre>
</td>
</tr>
<tr class="code">
<td class="docs">
<p>Module version
 </p>
</td>
<td class="code">
<pre><code><span class="variable">exports</span>.<span class="variable">version</span> = <span class="string">'0.0.2'</span>;
</code></pre>
</td>
</tr>	</body>
</html></tbody></table>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions