Subdomain routing

0 views
Skip to first unread message

Osaris

unread,
Oct 12, 2009, 8:51:32 AM10/12/09
to Pluf Users
Hello,

I'm a ruby on rails developer and PHP developer and I plan to play a
little bit with Pluf but I don't know how I can write route based on
URL of the application. In many rails app we use : user.myapp.com to
handle "multi-tenant" application. Maybe I should write a Pluf
middleware for that ?

Thanks for your help,

Osaris

Loic d'Anterroches

unread,
Oct 12, 2009, 11:38:32 AM10/12/09
to pluf-...@googlegroups.com
Hello,

Effectively, usually I just create a simple middleware and set the
corresponding user/site/whatever as a property of the $request object. I
am also a fan of the postgresql schemas, I can set the search path to a
given schema for the given user/site etc.

This is what I am doing for the farm hosting of InDefero.

loďc


Osaris

unread,
Oct 12, 2009, 11:46:29 AM10/12/09
to Pluf Users
Thanks Loïc, maybe you can put a non-strategic example of your
middleware. For the database part, you use a different database for
each of the user account or your database schema contains a relation
to the user in each table ? I'm more a Mysql/SQlite guy.

Regards,

osaris

On 12 oct, 17:38, Loic d'Anterroches <ti...@users.sourceforge.net>
wrote:
> loïc

Loic d'Anterroches

unread,
Oct 12, 2009, 2:52:25 PM10/12/09
to pluf-...@googlegroups.com
Osaris wrote:
> Thanks Loïc, maybe you can put a non-strategic example of your
> middleware. For the database part, you use a different database for
> each of the user account or your database schema contains a relation
> to the user in each table ? I'm more a Mysql/SQlite guy.

A bit edited... but basically I get the forge from the url and then I
set $request->forge = $theforge;
Then in all the views I can access $request->forge to act on it.
It does not look very nice because I am accessing the $GLOBALS directly,
but this is the most efficient way to do it and it is the only place
where I am doing it.

The schema stuff from PostgreSQL allows me to write the application as
if I had only one forge and split at the database level. A postgreSQL
schema is a bit like a database within a database. You can also add a
relation to the user/forge table in each object if you build your
application as being SaaS from the start (it was not my case, this is why).

loïc

<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/**
* Forge middleware.
*
* Switch to the right forge based on the url.
*/
class IDFA_Middleware_SetForge
{
/**
* Process the request.
*
* When processing the request, check the hostname and set the
* $request->forge corresponding to the forge. If no
* forge are found simply redirect to the indefero website.
*
* @param Pluf_HTTP_Request The request
* @return bool false or redirect.
*/
function process_request(&$request)
{
$sql = new Pluf_SQL('status=1 AND (domain=%s OR custdomain=%s)',
array($request->http_host,
$request->http_host));
$forges = Pluf::factory('IDFA_Forge')->getList(array('filter' =>
$sql->gen()));
if ($forges->count() != 1) {
return new
Pluf_HTTP_Response_Redirect('http://www.indefero.net/');
}
if ($forges[0]->allowssl == false and !empty($_SERVER['HTTPS'])) {
return new
Pluf_HTTP_Response_Redirect('http://'.$request->http_host);
}
IDFA_Middleware_SetForge_set($request, $forges[0]);
return false;
}

/**
* Process the response of a view.
*
* Reset the search path.
*
* @param Pluf_HTTP_Request The request
* @param Pluf_HTTP_Response The response
* @return Pluf_HTTP_Response The response
*/
function process_response($request, $response)
{
IDFA_Middleware_SetForge_back();
return $response;
}
}

function IDFA_Middleware_SetForge_set(&$request, $forge)
{
// Dynamic modification of the configuration.
$GLOBALS['_PX_config_old'] = $GLOBALS['_PX_config'];
// Update configuration variables (dynamic modification of
// $GLOBALS['_PX_config'];
IDFA_Middleware_SetForge_updateConf($forge);
$request->forge = $forge; // Here I set the forge to track it
$db = &Pluf::db();
$db->setSearchPath($forge->db_schema); // Here I set the search path
}

function IDFA_Middleware_SetForge_back()
{
$db = &Pluf::db();
$db->setSearchPath();
$GLOBALS['_PX_config'] = $GLOBALS['_PX_config_old'];
unset($GLOBALS['_PX_config_old']);
}

/**
* Directly modify the $GLOBALS array to set the configuration
* variables for this forge.
*
* @param IDFA_Forge
*/
function IDFA_Middleware_SetForge_updateConf($forge)
{
$GLOBALS['_PX_config']['git_repositories'] = ...

Osaris

unread,
Oct 12, 2009, 5:09:26 PM10/12/09
to Pluf Users
Ok thanks for the example.

The multi-tenant part for the database is another question but It
could be part of another middleware to avoid scoping to the forge (in
your example) for each select/insert/update/delete query. Do you think
it's a good idea and it's something possible with Pluf ?

On 12 oct, 20:52, Loic d'Anterroches <ti...@users.sourceforge.net>

Loic d'Anterroches

unread,
Oct 13, 2009, 12:14:45 PM10/13/09
to pluf-...@googlegroups.com
Osaris wrote:
> Ok thanks for the example.
>
> The multi-tenant part for the database is another question but It
> could be part of another middleware to avoid scoping to the forge (in
> your example) for each select/insert/update/delete query. Do you think
> it's a good idea and it's something possible with Pluf ?

I was thinking about that to be able to use mongodb for the farm hosting
of the forges. Some kind of ability to update the queries on the fly to
add a "where forge=foo" clause. At the end, I think that if you need
such things, better to tune your data access layer directly and do not
use an automated way to do it.

But you need to notice that this scenario is really just because I
created InDefero without thinking at providing as a service first. This
was done after. If you create you software to be delivered as a service
right from the start, you should really think about your usage patterns
and without overengineering the stuff, think a bit about the scaling
issues. You have total freedom.

In any cases, your first bottleneck will be the database, so you need to
just think about the following issue: what do I do if the amount of
write is such that one DB server cannot handle it? You just need a rough
idea, anyway, it takes time to get the traction to be obliged to use
more than one master. Twitter used only one db server for ages.

loïc
Reply all
Reply to author
Forward
0 new messages