What makes PHP great and easy is that hosting it is a piece of cake. Put a file named .php and you’re done. This is why it has a global impact into web development and remains a good starting point for new comers.
When you try to move out of it, using the populars Python or Ruby, it starts to get complicated. If you aren’t goint with the CGI-way because it appears to be too old school, you’ll start asking you this question: “Which framework do I have to pick?”
But start asking yourself: “What is a web framework?”. The visible parts of it are generally a templating system, an abstraction layer with a database (aka ORM or sometimes DAO) and a simple way to glue everything together mapping an URL to a function That is what you see and what you don’t see is the layer between the web server and your application. Most of the time, "print" goes into stdout (in the console) and not on the page itself. For Python and using Apache, you have different solutions. Some of them:
- CGI, the old one;
- FastCGI, a better alternative;
- mod_python
- mod_wsgi
The last one get a lot of attention, because of its simplicity and powerfulness. It’s basically an interface that your application has to respect. Here is a python example:
def application(environ, start_response):
start_response("200 OK", [("Content-Type", "text/plain")])
return ["Hello, world!"]
Giving this file to mod_wsgi will get you the famous Hello World. environ contains the environment variables, similar to the PHP’s $_ENV.
This is was for the simplicity, now let’s explore the powerfulness. This API enables to chain, pipe applications. You can insert, between the server and the real application, middlewares. So middleware are applications that will act like an application to the server and like a server to the application. An example with a ROT13 encoding middleware:
def rot13(app):
def new_app(environ, start_response):
response = app(environ, start_response)
return [line.encode("rot13") for line in response]
return new_app
application = rot13(application)
Now, application will call the original one and perform a rot13 encoding to its output. That’s it, this is a basic middleware. What is great about that is that any middleware is easily reusable, you can chaim them the way you need. Reusable means that there are a lot of WSGI Middlewares available you can reuse directly.
Using functions cannot be enough for you, this is why you’ll meet a lot of functors more than functions. The same middleware written using a functor:
class Rot13Middleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
response = self.app(environ, start_response)
return [line.encode("rot13") for line in response]
application = new Rot13Middleware(app)
The application will return the original message now because doing rot13 two times is the identify function. A functor is basically a class that can act like a function.
WSGI is so brilliant that he made little brothers, Rack in Ruby:
app = lambda do |env|
[200,
{’Content-Type’ => ’text/plain’},
"Hello, world!"]
end
def rot13decorator(func)
lambda do |env|
status, headers, response = func.call(env)
[status, headers, response.tr("A-Ma-mN-Zn-z", "N-Zn-zA-Ma-m")]
end
end
app = rot13decorator(app)
which inspires Jack using JavaScript (via Rhino and Jetty):
function app(env) {
return [200,
{"Content-Type": "text/plain"},
"Hello, world!"];
}
function rot13decorator(func) {
return function(env) {
var response = func.invoke(env);
return [response[0], response[1], rot13(response[2])];
}
}
app = rot13decorator(app)
Both Ruby and Javascript have an object-oriented way of doing applications and middlewares too. See the full code on Github.
This to say that using a tool (call it framework) that follows such an interface will enable you to reuse existing middlewares easily. For example Rack has a JSONP middleware. JSONP means adding a function call around a JSON object, this is the kind of simple, reusable things that can be done via a middleware.
I loved LEGO®’s as a kid, and still have stars in my eyes when I see small toys I can play with and build everything my crazy mind might come up with.
