Tuesday, April 16, 2013

NGINX Awesomeness: A Simple, Powerful Web Server and More

A 2MB exe which runs a web server to rival Apache? Well, maybe not, but if you Like Simple then you will Like NGINX. In terms of power it kicks Mongoose's ass I have to say because that critter, whom I am fond  of, was pretty limited. So, ff you want to run multiple sites, reverse proxy, finely control everything HTTP and more then NGINX is your new best friend

Download and run and you have a webserver on http://localhost serving up whatever is in your HTML folder. I've stripped down the conf/nginx.conf file in order to learn and explain it here:


http {
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}
events {
    worker_connections  1024;
}

This obviously sets up an HTTP server on your machine listening on port 80. It's actually just the explicit version of the default settings and so equivalent to:


http {
    server {}
}
events {}

If you like being Spartan!

Next: want a second server (host name)? Just add a new server section:
server {
    server_name  mydomain.com;
    location / {
        root   /somewhere/else/;
        autoindex on;
    }
}
The autoindex setting provides an automatic directory listing (great for local test servers).

Of course you can configure logging (even per server), HTTP settings (e.g. keep alive stuff), mime types, SSL, hostname wildcards, virtual directories, error pages, gzip (nice), deny access (for .htaccess you need a converter) and all the usual stuff you need. But what get's me excited is the reverse proxy stuff.

Our company uses an expensive, high tech appliance for reverse proxy (and load balancing) functionality. This helps keep our web servers out of the DMZ and provides a neat front so that we can have multiple different web servers behind one application on one domain. The downside is you need a degree in it to configure it. NGINX is Simple - remember! Watch this:

Let's say you have another web server running PHP and you want NGINX to reverse proxy it. Simply pass all URLs ending in .php to that server with the location command's RegEx functionality:


location ~ \.php$ {
    proxy_pass   http://myphp.mydomain.com:8080;
}
That's awesome IMO. You need some serious expertise and clicking to get that done in our enterpise level applicance whose name begin's with "F" and ends with "5" but shall otherwise remain unnamed.

So sharpen up your RegEx skills and run your whole organisation's web infrastructure through one domain if you like.

Wednesday, April 10, 2013

OptiBrowser: Managing Links in a Multi-Browser World

As a web developer I have several browsers installed on my PC. This is not only for testing apps on different browsers but allows you to run the same app as a different user at the same time - something many web apps don't offer because they store session state in a cookie which is shared among windows of the same browser.

That's all fine but what about the default browser? Each OS allows you one and only one default browser. This means that when you click a link in an email it will always open in your default browser. If you're like me, and your default browser is internet explorer (don't ask), you find yourself copying the link and pasting it into Chrome.

Enter OptiBrowser!



OptiBrowser is your new default browser and yet it's not a browser at all. It's simply a menu which let's you choose which browser you want to start the link you just clicked in. Press <Enter> and it will start in your default browser. Of course this only applies to links you click outside of the browser - links clicked in a browser say in that browser.

Check it out on GitHub (cawoodm/optibrowser) and, if you have any issues post them there. It's written in C# (.NET 4) and compiled and tested under Windows 7 so far. Feel free to fork and improve.

Thursday, February 7, 2013

Crafty Tennis: A Component-Entity Game in JavaScript

Been dreaming of making a game for some time now and have been very interested in Component-Entity Systems which are a great way of keeping complexity down in a game.

I won't go through all the details here but suffice it to say you can keep complexity linear by either  adding new entities to your game (more "things" in the game) or by adding new components (more "functionality"). You then simply tell each new entity you add which components it has.


// Player Left (with AI)
Crafty.sprite(32, "img/padleft.run.png", {
  padleft: [0, 0]
});
Crafty.e("Paddle, 2D, DOM, Color, Multiway, Bound, AI, padleft, SpriteAnimation")
.color('rgb(255,0,0)')
.attr({ x: 20, y: H/2, w: 32, h: 32, player: 1 })
.bound({minX: 0, minY: 0, maxX: W/2, maxY: H})
.multiway(4, { W: -90, S: 90, D: 0, A: 180 })
.difficulty(3)
.bind('NewDirection', runner)
.animate('run', 0, 0, 5) // From x=0, y=0 to x=5 (6 frames)
;


Check it out on GitGub (cawoodm/tennis) or download it - it's actually quite fun to play!


Of course all this development was made possible by the excellent (and free) in-browser editor called Scripted - it's a poor man's Sublime Text.

Monday, January 7, 2013

Clean Your Path

Note: This is a Windows tip!

Each time you install new software, especially nerdy, developer stuff, it tends to add itself to your system PATH. For single .exe programs (e.g. curl or git) I find this wasteful so I've devised a cunning plan. Let's say you install curl.exe in C:\some\folder\curl


  1. Remove the folder from your system path
  2. Create a curl.cmd text file in C:\windows\system32
  3. Edit this text file and add the following: C:\some\folder\curl\curl.exe %*
Now, open a DOS window and run curl google.com - it works! How?

  • %* passes all parameters on to curl.exe
  • C:\windows\system32 is always on your system path
I recommend doing this for all your favorite command line programs and even your favorite editor. My new favorite is Scripted!

Wednesday, December 19, 2012

Easy MicroTemplating

I'm a huge fan of templates in that I always want to separate my view from my code. But I don't like to include hundreds of kilobytes of some library just to get templating - so I made my own in a few lines which I can just copy into any project.

The most basic usage is to pass it data and a template and get the result:
microTemplate({name:'Jack'}, '<h1>Hello {{name}}</h1>');
This will return:
<h1>Hello Jack</h1>

Now there are different ways of using it. You can specify a DOM element which contains your template so if you have this in your HTML:
<div id="op"><h1>Hello {{name}}</h1></div>
You can just do:
microTemplate({name:'Jack'}, $('#op')[0]);
This will automatically write the result back into your div.

It supports arrays so:
var friends = [{name:'Jack'},{name:'Jill'}];
microTemplate(friends, '<h1>Hello {{name}}</h1>', $('#op3')[0]);
Will result in:
<h1>Hello Jack</h1>
<h1>Hello Jill</h1>

If you want a table or an ordered list you'll need to specify header and footer:
microTemplate(friends, '<li>{{name}}</li>', $('#op4')[0], '<ol>', '</ol>');
Which will result in:
<ol>
 <li>Jack</li>
 <li>Jill</li>
</ol>

I think it's awesome!


<!doctype html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
  <script>
  $(function() {
    microTemplate({name:'Jack'}, $('#op')[0]);
    microTemplate({name:'Jack'}, '<h1>Hello {{name}}</h1>', $('#op2')[0]);
    microTemplate([{name:'Jack'},{name:'>>Jill<<'}], '<h1>Hello {{name}}</h1>', $('#op3')[0]);
    microTemplate([{name:'Jack'},{name:'Jill'}], '<li>{{name}}</li>', $('#op4')[0], '<ol>', '</ol>');
  });
  
  function microTemplate(data, temp, el, head, foot) {
    if (typeof temp.innerHTML=='string') {el=temp;temp=temp.innerHTML;}
    data = [].concat(data);
    var res = head||'';
    for (var i in data) {
      res += temp;
      for (var f in data[i]) {
        res = res.replace(new RegExp('{{{'+f+'}}}', 'ig'), data[i][f]);
        res = res.replace(new RegExp('{{'+f+'}}', 'ig'), data[i][f].replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'));
      }
    }
    res += foot||'';
    if (el && typeof el.innerHTML == 'string') el.innerHTML = res;
    return res;
  } 
  </script>
</head>
<body>

<div id="op"><h1>Hello {{name}}</h1></div>
<div id="op2"></div>
<div id="op3"></div>
<div id="op4"></div>

</body>
</html>


Saturday, December 15, 2012

ssiJS: Server Side Includes on the Client

I cut my teeth on classic ASP where you build applications by including various blocks using SSI (server-side include) syntax. If you wanted to include common content (e.g. branding or a copyright statement) inside your <body> you would include it like this:
<!-- #include file="copyright.asp" -->

Aside from <iframe> there is no way to include content from other sites using HTML. You need JavaScript so I wrote a 3-liner jQuery script which does just that. Consider this HTML:
<div class="ssi" data-url="copyright.html"></div>

Add the following JavaScript to your $(function(){}); and you'll have client side includes:

$.each($('div.ssi'), function(a,b) {
$(b).load(b.getAttribute('data-url'));
});

What does this do? It iterates through all divs with the class 'ssi' and loads their content asynchronously from the url specified in their 'data-url' attribute. I think this is neat.

Full source:


<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script>
$(function() {
$.each($('div.ssi'), function(a,b) {
$(b).load(b.getAttribute('data-url'));
});
});
</script>
</head>
<body>
<div class="ssi" data-url="a.html"></div>
<div class="ssi" data-url="b.html"></div>
</body>
</html>

Tuesday, November 1, 2011

YQL: All the Data you can Eat

I love SQL and I love data. Just give me a database and some SQL and I'll analyse the bejeesuz out of it. I also like flexible interfaces. YQL provides all of this. The Yahoo Query Language is basically 2 things:
  1. A huge data source
  2. An easy query language which resembles SQL
  3. Standardized output format (JSON or XML)
OK, that was 3 things but I'm not going back to change my assertion just because I thought of an extra thing whilst typing. And, speaking of inaccuracies, I saaay "data source" but actually it's mostly just passing on data it gets from elsewhere. Let's dive in:

Say you wanna query an RSS feed:
SELECT * FROM rss WHERE url = 'http://sports.yahoo.com/top/rss.xml'

This will return the RSS items from the Yahoo! sports site. You can of course specify multiple feeds using IN (url1, url2) and you can also sort (example).

You can query weather, flickr for photos, find restaurants in San Francisco , list music videos ... I think you get the picture.

There is also the YQL Console, a place to test out your queries. It will generate the link which you can then use in your applications to query data. As you will see, you can specify the output format as XML or JSON:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.oceans&format=json&callback=showOceans

The callback function wraps your data in a javascript function which means you just AJAX the URL above and your callback function will automatically be executed.

Finally the really gr8 thing about YQL is that it's free and it's cross-domain compatible. If you've ever made an application which fetches data from a different domain you'll know of the issues involved. Modern browsers just don't allow it unless the server says it's OK. YQL always adds the "it's OK header" (Access-Control-Allow-Origin: *) which means it damn well works. Very nice of dem folks at Yahoo!.

Finally, the other of the final 3 great things is that you can literally query (scrape) any web page on the, er, web. You can query normal HTML pages or XHTML or XML sources.

Coming soon, my jQuery Mobile RSS Reader app which uses YQL and Local Storage to save your RSS.