Viewed   72 times

Is there a way to set up hostname based routing in Symfony2?

I didn't find anything about this topic in the official documentation.
http://symfony.com/doc/2.0/book/routing.html

I want to route the request based on the given hostname:
foo.example.com
bar.example.com
{{subdomain}}.example.com

So in essence, the controller would get the current subdomain passed as a parameter.

Similar to the Zend solution:
http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.hostname

$hostnameRoute = new Zend_Controller_Router_Route_Hostname(
    ':username.users.example.com',
    array(
        'controller' => 'profile',
        'action'     => 'userinfo'
    )
);
$plainPathRoute = new Zend_Controller_Router_Route_Static('');

$router->addRoute('user', $hostnameRoute->chain($plainPathRoute));

I hope that it's possible and I just missed it somehow.
Thanks in advance!

 Answers

2

This is my solution:

In the config.yml inside app dir add the following lines:

services:
   kernel.listener.subdomain_listener:
       class: AcmeDemoBundleListenerSubdomainListener
       tags:
           - { name: kernel.event_listener, event: kernel.request, method: onDomainParse }

Then create the class SubdomainListener.php as:

<?php

namespace AcmeDemoBundleListener;

use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentEventDispatcherEvent;

class SubdomainListener
{
   public function onDomainParse(Event $event)
   {
       $request = $event->getRequest();
       $session = $request->getSession();

       // todo: parsing subdomain to detect country

       $session->set('subdomain', $request->getHost());
   }
}
Monday, December 5, 2022
4

Finally found a solution to this problem after reading the source for ssh-add and by reading this very old article from Wez Furlong where he talks about adding PTY support to PHP.

To quote the article:

What this does is similar to creating a pipe to the process, but instead creates master (for your script) and slave (for the process you're running) pty handles using the /dev/ptmx interface of your OS. This allows you to send to, and capture data from, applications that open /dev/tty explicitly--and this is generally done when interactively prompting for a password.

Turns out Symfony Process also supports PTY so the original code only needed a couple of changes. First I need to specify I want to use PTY instead of pipes by calling setPty(true). Then I need to simulate that the user has pressed ENTER after inputting the password simply by appending a line feed to the input.

The final code would look something like this (with comments on the changed lines)

use SymfonyComponentProcessProcess;

$keyPath = '<path to key>';
$keyPassword = '<password for unlocking the key>';
$socketPath = '<path to ssh-agent socket>';

$sshAdd = new Process(
    "ssh-add {$keyPath}",
    null,
    [
        'SSH_AUTH_SOCK' => $socketPath
    ],
    $keyPassword . "n"   // Append a line feed to simulate pressing ENTER
);
$sshAdd->setPty(true);   // Use PTY instead of the default pipes
$sshAdd->run();
Tuesday, December 20, 2022
 
bang
 
5

You should make the xampp/htdocs/zadanie directory your document root, or move everything in it to the htdocs directory.

Friday, November 18, 2022
 
dcmaxxx
 
2

I ended up looking at the documentation on the symfony site, as well as the source code on github (Route.php, RouteCollection.php, RouteCompiler.php) and came up with my own basic router.

Just like symfony, I allow 4 arguments to be passed to the route class -> 1) the pattern, 2) the default controller/action, 3) regex requirements for each variable in the pattern, and 4) any options - I haven't coded for this yet as it's not in my requirements.

My main/front controller (index.php) only talks to the static Router class which has access to the other route classes in the libroute namespace.

Router::Map basically compiles a regex string (along with default controller/action and variable names) that gets passed to the compiledRouteCollection which is used in Router::_Process to match the httpRequest against. From there, if there is a match in the process method then i set the controller/action/args based on the values of the matched compiledRoute default controller/action. If there is not a preg_match then i use the default controller/action/args from the request object. The rest is cake...

I hope someone finds this useful and it's able to save them the time I spent today working on this. Cheers!

index.php

require_once 'config/config.php';
require_once 'lib/autoload.php';
libRouter::Map(
    'users_username_id',
    'users/{username}/{id}',
    array('controller' => 'testController', 'action' => 'users')
);
libRouter::Route(new libRequest());

router.php

namespace lib;

class Router {
protected static $_controller;
protected static $_action;
protected static $_args;
protected static $_compiledRouteCollection;
private static $_instance;

private function __construct() {
    self::$_compiledRouteCollection = new librouteCompiledRouteCollection();
}

public static function Singleton() {
    if(!isset(self::$_instance)) {
        $className = __CLASS__;
        self::$_instance = new $className;
    }
    return self::$_instance;
}

public static function Route(Request $request, $resetProperties = false) {
    self::Singleton();

    self::_Process($request,$resetProperties);

    $className = '\app\controllers\' . self::$_controller;
    if(class_exists($className, true)) {
        self::$_controller = new $className;

        if(is_callable(array(self::$_controller, self::$_action))) {
            if(!empty(self::$_args)) {
                call_user_func_array(array(self::$_controller, self::$_action), self::$_args);
            } else {
                call_user_func(array(self::$_controller, self::$_action));
            }
            return;
        }
    }
    self::Route(new libRequest('error'),true);
}

public static function Map($name, $pattern, array $defaults, array $requirements = array(), array $options = array()) {
    self::Singleton();
    $route = new librouteRoute($pattern,$defaults,$requirements,$options);
    $compiledRoute = $route->Compile();
    self::$_compiledRouteCollection->Add($name,$compiledRoute);
}

private static function _Process(Request $request, $resetProperties = false) {
    $routes = array();
    $routes = self::$_compiledRouteCollection->routes;
    foreach($routes as $route) {
        preg_match($route[0]['regex'], $request->GetRequest(), $matches);
        if(count($matches)) {
            array_shift($matches);
            $args = array();
            foreach($route[0]['variables'] as $variable) {
                $args[$variable] = array_shift($matches);
            }
            self::$_controller = (!isset(self::$_controller) || $resetProperties) ? $route[0]['defaults']['controller'] : self::$_controller;
            self::$_action = (!isset(self::$_action) || $resetProperties) ? $route[0]['defaults']['action'] : self::$_action;
            self::$_args = (!isset(self::$_args) || $resetProperties) ? $args : self::$_args;

            return;
        }
    }
    self::$_controller = (!isset(self::$_controller) || $resetProperties) ? $request->GetController() : self::$_controller;
    self::$_action = (!isset(self::$_action) || $resetProperties) ? $request->GetAction() : self::$_action;
    self::$_args = (!isset(self::$_args) || $resetProperties) ? $request->GetArgs() : self::$_args;
}
}

request.php

namespace lib;

class Request {
protected $_controller;
protected $_action;
protected $_args;
protected $_request;

public function __construct($urlPath = null) {
    $this->_request = $urlPath !== null ? $urlPath : $_SERVER['REQUEST_URI'];

    $parts = explode('/', $urlPath !== null ? $urlPath : $_SERVER['REQUEST_URI']);
    $parts = array_filter($parts);

    $this->_controller = (($c = array_shift($parts)) ? $c : 'index').'Controller';
    $this->_action = ($c = array_shift($parts)) ? $c : 'index';
    $this->_args = (isset($parts[0])) ? $parts : array();
}

public function GetRequest() {
    return $this->_request;
}

public function GetController() {
    return $this->_controller;
}

public function GetAction() {
    return $this->_action;
}

public function GetArgs() {
    return $this->_args;
}
}

route.php

namespace libroute;

class Route {
private $_pattern;
private $_defaults;
private $_requirements;
public $_options;

public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array()) {
    $this->SetPattern($pattern);
    $this->SetDefaults($defaults);
    $this->SetRequirements($requirements);
    $this->SetOptions($options);
}

public function SetPattern($pattern) {
    $this->_pattern = trim($pattern);

    if($this->_pattern[0] !== '/' || empty($this->_pattern)) {
        $this->_pattern = '/'.$this->_pattern;
    }
}

public function GetPattern() {
    return $this->_pattern;
}

public function SetDefaults(array $defaults) {
    $this->_defaults = $defaults;
}

public function GetDefaults() {
    return $this->_defaults;
}

public function SetRequirements(array $requirements) {
    $this->_requirements = array();
    foreach($requirements as $key => $value) {
        $this->_requirements[$key] = $this->_SanitizeRequirement($key,$value);
    }
}

public function GetRequirements() {
    return $this->_requirements;
}

public function SetOptions(array $options) {
    $this->_options = array_merge(
        array('compiler_class' => 'lib\route\RouteCompiler'),
        $options
    );
}

public function GetOptions() {
    return $this->_options;
}

public function GetOption($name) {
    return isset($this->_options[$name]) ? $this->_options[$name] : null;
}

private function _SanitizeRequirement($key, $regex) {
    if($regex[0] == '^') {
        $regex = substr($regex, 1);
    }

    if(substr($regex, -1) == '$') {
        $regex = substr($regex,0,-1);
    }

    return $regex;
}

public function Compile() {
    $className = $this->GetOption('compiler_class');
    $routeCompiler = new $className;

    $compiledRoute = array();
    $compiledRoute = $routeCompiler->Compile($this);
    return $compiledRoute;
}
}

routeCompiler.php

namespace libroute;

class RouteCompiler {

//'#/tellme/users/[wd_]+/[wd_]+#'
public function Compile(Route $route) {
    $pattern = $route->GetPattern();
    $requirements = $route->GetRequirements();
    $options = $route->GetOptions();
    $defaults = $route->GetDefaults();
    $len = strlen($pattern);
    $tokens = array();
    $variables = array();
    $pos = 0;
    $regex = '#';

    preg_match_all('#.{([wd_]+)}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
    if(count($matches)) {
        foreach($matches as $match) {
            if($text = substr($pattern, $pos, $match[0][1] - $pos)) {
                $regex .= str_replace('/', '/', $text).'/';
            }
            if($var = $match[1][0]) {
                if(isset($requirements[$var])) {
                    $regex .= '('.$requirements[$var].')/';
                } else {
                    $regex .= '([wd_]+)/';
                }
                $variables[] = $match[1][0];
            }
            $pos = $match[0][1] + strlen($match[0][0]);

        }
        $regex = rtrim($regex,'/').'#';
    } else {
        $regex .= str_replace('/', '/', $pattern).'#';
    }

    $tokens[] = array(
        'regex' => $regex,
        'variables' => $variables,
        'defaults' => $defaults
    );
    return $tokens;
}
}

compiledRouteCollection.php

namespace libroute;

class CompiledRouteCollection {
public $routes;

public function __construct() {
    $this->routes = array();
}

public function Add($name, array $route) {
    $this->routes[$name] = $route;
}
}
Monday, August 29, 2022
 
stim
 
37

From this article on the Red Hat Knowledgebase:

How do I disable the zeroconf route so that the system will boot without the 169.254.0.0 / 255.255.0.0 route?

Symptom:

Every time the system boots, the zeroconf route (169.254.0.0) is enabled. You manually disable it by turning off the firewall and remove the route with 169.254.0.0 / 255.255.0.0 using the route command.

Example output of the route with the zeroconf route enables would like similar to the following:

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.15.50.0      *               255.255.252.0   U     0      0        0 eth0
169.254.0.0     *               255.255.0.0     U     0      0        0 eth0

Solution:

To disable the zeroconf route during system boot, edit the /etc/sysconfig/network file and add the following NOZEROCONF value to the end of the file:

NETWORKING=YES
HOSTNAME=localhost.localdomain
NOZEROCONF=yes
Wednesday, September 21, 2022
 
templar
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :