php 5.4 + htrouter: Your personal Apache 2.2 compatible server

Warning: This blogpost has been posted over two years ago. That is a long time in development-world! The story here may not be relevant, complete or secure. Code might not be complete or obsoleted, and even my current vision might have (completely) changed on the subject. So please do read further, but use it with caution.
Posted on 22 Dec 2011
Tagged with: [ htrouter ]  [ php5.4 ]  [ webserver

Version 5.4 is soon to be launched as the next new stable release of PHP. Granted, there will not be major changes like we saw in version 5.3, but it will still have some nifty new features. Two of the most important ones: traits and the internal web server. This post is about the latter one. The new web-server makes it possible to run your PHP code through your browser even when you don’t have your own web-server like Apache or nginx installed. It has got some advantages, but this of course has raised some serious discussions: should PHP even be distributed with a web-server and if so, how can we make sure that it won’t be misused as a production server? Well, we really can’t forbid people to (mis)use this, but we hope most of us will use common sense.. The project in this blog-post however, can be considered as “The Enabler”. It can be a powerful tool for developers, but makes it easier for people to misuse the web-server. Time of course, will tell if this will be the case, but I think I’ve created a (simple) tool that will create the new Dr Jeckyl web-server into a Mr Hyde… What could possibly go wrong? :-)

Introducing: the .htaccess

Most frameworks, CMS systems and projects are being run on an Apache web-server platform. One of the benefits is that this platform is not only very stable, but also got a lot of extra functionality that can be implemented through modules. These modules can be configured through Apache’s main configuration or through user-defined configurations - mostly known as .htaccess files.

Most .htaccess files are used for 2 things: rewriting url’s and authentication/authorization. The authentication comes in handy in combination with a .htpasswd file, where you can store a user/password combination for the persons that can log into your website. We all have seen it, and most of you have “secured” at least a portion of a website (it’s also a good way to secure a preview website for instance). Apache accepts even more advanced ways of authentication, for instance through LDAP.

Second common feature of .htaccess files: the URL rewriting. Sometimes it’s just nicer to go to: http://www.example.org/this/is/my/page, instead of http://www.example.org/index.php?page=this&article=is_my_blog. With the help of URL-rewriting, it’s easy to achieve this, and create permalinks and such. Most frameworks have a so-called front-controller where all urls will be redirected to (in symfony’s case, this would be app_dev.php or app.php, and Zend Framework uses the more standard index.php for this).

The problem with the new PHP 5.4 internal web-server is that it isn’t Apache. Thus it does not know anything about htaccess. Even when you have defined your .htaccess to do authentication, the internal PHP web-server will ignore it, while in production, the authentication will be needed (if you will be running Apache, of course). Also, you need to reroute everything manually through your app_dev.php, so your URL’s don’t really match the way they will be on your production.

Introducing: the php 5.4 webserver

The PHP internal web-server has the opportunity to route all requests it receives through a single PHP file.

$ php -S 127.0.0.1:80 router.php

The router.php itself can be a simple program that parses the request, and checks if it’s something that needs to be passed onto your normal PHP code (for instance, your index.php) or maybe it will be something that can be served directly from disk. A simple router.php doesn’t have to be very complex:

<?php
    if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) { 
        return false;
    } else {
        include "index.php";
    }

This is one of the most basic router.php scripts that are available: if it’s in image file, it will load directly the image from disk (by returning false). Otherwise, it will include the main index.php file, so everything gets rerouted through that file. You get automatically some very crude URL-rewrite functionality: everything will be rerouted through index.php, so when you go to : http://server:8080/my/url, it will redirect to index.php with the request-uri being:

[REQUEST_URI] => /my/url

But of course, it is in no way compatible with a regular .htaccess file. That is where this project comes into play:

Introducing: the HTRouter project

The code itself is pretty simple: it just loads all available “modules”, parses a .htaccess file found in the main directory and executes the things that normally Apache would do for you. In the end, it will pass control to your application (if needed). So in essence, it’s the Apache module-functionality completely rewritten in PHP.

All the modules that can be loaded, will mimic the actual modules as found in Apache itself. So there is a mod_rewrite module, a mod_auth module for authentication, a mod_authn_file module that will authenticate by reading users from a htpasswd file etc.

Of course, the code is on github: https://github.com/jaytaph/htrouter

Note: the code is not finished! There are still lots of things that needs to be implemented:

  • mod_rewrite, so we can rewrite url’s (pretty important)
  • mod_alias, so we can alias url’s (not so important, but nifty enough)
  • Package everything through PHAR

So there is still some work left. However, the basics are beginning to show, and the standard basic authentication through htpasswd files are functional. I’m really hoping this will be a good way to help developers that will use the standard web-server but still crave .htaccess functionality.

Again, I’m terribly sorry for all developers who now will get the idea it might be a good idea to use this in production. Please don’t. It will probably never will be a good idea, HOWEVER, and this is still something I truly think can and will happen: it will be a perfect system for backend-maintenance or as an admin-panel web interface. Normally, you don’t need threading and serve many requests but sometimes you want the simple .htaccess handling. I’m sure the PHP internal web-server will evolve over time into something more robust, and hopefully, this project will be part of generalize the usage of .htaccess.