Posted by Dan Sosedoff
on July 04, 2009
Developing with Merb or Sinatra ? Like web server nginx ? Ok, lets go.
Basically, Merb/Sinatra uses thin (based on eventmachine) server module, so it is working as stand-alone application. So, there is a way to connect nginx with these applications. Very simple – all you need to proxy requests to backend server. And all static files will be served by nginx.
upstream your_app {
server 127.0.0.1:YOUR_PORT_NUMBER;
}
server {
server_name YOUR_SERVERNAME;
listen 80;
charset utf-8;
client_max_body_size 64M; # maximum of proxied filesize (for uploads)
location / {
root /path/to/app/root;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect false;
if (-f $request_filename) {
break;
}
if (!-f $request_filename) {
proxy_pass http://your_app;
break;
}
}
# static content (images, flash, styles, etc.)
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|swf)$ {
root /path/to/your/public/dir;
access_log off;
}
}
Then, all you need – start your application in daemon mode. Dont forget to bind application server to listen only on local address (127.0.0.1).
Posted by Dan Sosedoff
on July 04, 2009
!!! CONSIDER THIS AS AN UPDATE:Rails-like PHP Url Router
Here is simple url parser, that produces output parameters lile: controller, action, parameters. Also, it support simple virtual key rules, “rails” style.
For example, url like “http://foo.bar/book/view/12″ will produce parameters: controller = book, action = view, id = 12.
Here is php code:
<?
/* ------------------------------------------------------------- */
/* URL Router class */
/* ------------------------------------------------------------- */
class Router {
static protected $instance;
static protected $controller;
static protected $action;
static protected $params;
static protected $rules;
public static function getInstance() {
if (isset(self::$instance) and (self::$instance instanceof self)) {
return self::$instance;
} else {
self::$instance = new self();
return self::$instance;
}
}
private static function arrayClean($array) {
foreach($array as $key => $value) {
if (strlen($value) == 0) unset($array[$key]);
}
}
private static function ruleMatch($rule, $data) {
$ruleItems = explode('/',$rule); self::arrayClean(&$ruleItems);
$dataItems = explode('/',$data); self::arrayClean(&$dataItems);
if (count($ruleItems) == count($dataItems)) {
$result = array();
foreach($ruleItems as $ruleKey => $ruleValue) {
if (preg_match('/^:[\w]{1,}$/',$ruleValue)) {
$ruleValue = substr($ruleValue,1);
$result[$ruleValue] = $dataItems[$ruleKey];
}
else {
if (strcmp($ruleValue,$dataItems[$ruleKey]) != 0) {
return false;
}
}
}
if (count($result) > 0) return $result;
unset($result);
}
return false;
}
private static function defaultRoutes($url) {
// process default routes
$items = explode('/',$url);
// remove empty blocks
foreach($items as $key => $value) {
if (strlen($value) == 0) unset($items[$key]);
}
// extract data
if (count($items)) {
self::$controller = array_shift($items);
self::$action = array_shift($items);
self::$params = $items;
}
}
protected function __construct() {
self::$rules = array();
}
public static function init() {
$url = $_SERVER['REQUEST_URI'];
$isCustom = false;
if (count(self::$rules)) {
foreach(self::$rules as $ruleKey => $ruleData) {
$params = self::ruleMatch($ruleKey,$url);
if ($params) {
self::$controller = $ruleData['controller'];
self::$action = $ruleData['action'];
self::$params = $params;
$isCustom = true;
break;
}
}
}
if (!$isCustom) self::defaultRoutes($url);
if (!strlen(self::$controller)) self::$controller = 'home';
if (!strlen(self::$action)) self::$action = 'index';
}
public static function addRule($rule, $target) {
self::$rules[$rule] = $target;
}
public static function getController() { return self::$controller; }
public static function getAction() { return self::$action; }
public static function getParams() { return self::$params; }
public static function getParam($id) { return self::$params[$id]; }
}
?>
Basic usage:
$router = Router::getInstance(); // init router
$router->addRule('/books/:id/:keyname',array('controller' => 'books', 'action' => 'view')); // add simple rule
// add some more rules
$router->init(); // execute router
So, as you can see, the router class can be accessible from anywhere in your code. Just because the class has beed designed as one-instance object, you cannot call for new instance. To get instance of router you need to call Router::getInstance() instead.
We have added simple rule for url`s like this ‘/books/12345/this-is-a-book-keyname’. Default routing system will identify this url incorrectly (controller => books, action => 12345). So the action 12345 not exists. That`s why we need to add custom rule. It will parse this url correctly: controller => books, action => view. And the rest of parameters will be automatically added to parameteres array. To access this array you need to call $router->getParams(); If you need to get just one parameter, call directly: $var = $router->getParam(0).
This router is really simple and can be used in small web sites that not require complete framework. Also it is fast.
Download file Router.php
View paste