tip of the day. The power of routes

514 views
Skip to first unread message

mdipierro

unread,
Oct 17, 2010, 10:03:25 PM10/17/10
to web2py-users
Replace your web2py/routes.py with this:

------------- begin routes.py-----------
try: config=open('routes.conf','r').read()
except: config=''
def auto_in(apps):
routes=[
('/robots.txt','/welcome/static/robots.txt'),
('/favicon.ico','/welcome/static/favicon.ico'),
('/admin$a','/admin$a'),
]
for a,b in [x.strip().split() for x in apps.split('\n') \
if x.strip() and not x.strip().startswith('#')]:
if not b.startswith('/'): b='/'+b
if b.endswith('/'): b=b[:-1]
app = b.split('/')[1]
routes+=[
('.*:https?://(.*\.)?%s:$method /' % a,'%s' % b),
('.*:https?://(.*\.)?%s:$method /static/$a' % a,'%s/static/
$a' % app),
('.*:https?://(.*\.)?%s:$method /appadmin/$a' % a,'%s/
appadmin/$a' % app),
('.*:https?://(.*\.)?%s:$method /$a' % a,'%s/$a' % b),
]
return routes

def auto_out(apps):
routes=[]
for a,b in [x.strip().split() for x in apps.split('\n') \
if x.strip() and not x.strip().startswith('#')]:
if not b.startswith('/'): b='/'+b
if b.endswith('/'): b=b[:-1]
app = b.split('/')[1]
routes+=[
('%s/static/$a' % app,'static/$a'),
('%s/appadmin/$a' % app, '/appadmin/$a'),
('%s/$a' % b, '/$a'),
]
return routes

routes_in=auto_in(config)
routes_out=auto_out(config)
------------------- END ---------------

what does it do? It writes routes for you based on a simpler routing
configuration file called routes.conf. here is an example:

----- BEGIN routes.conf-------
127.0.0.1 /examples/default
domain1.com /app1/default
domain2.com /app2/default
domain3.com /app3/default
----- END ----------

It maps a domain (the left had side) into an app and it shortens the
URLs for the app, by removing the listed path prefix. That means

http://domain1.com/index will be mapped into /app1/default/index
http://domain2.com/index will be mapped into /app2/default/index

It is safe in that it preserves admin, appadmin, static files,
favicon.ico and robots.txt.

http://domain1.com/favicon.ico
http://domain1.com/robots.txt
http://domain1.com/admin/... /admin/...
http://domain1.com/appadmin/... /app1/appadmin/...
http://domain1.com/static/... /app1/static/...

and vice-versa.

It does assume one app per domain.

I think something like this should be default since lots of people
find routes.py hard to work with.
Comments? Suggestions?

Massimo

mdipierro

unread,
Oct 17, 2010, 10:07:56 PM10/17/10
to web2py-users
I put the script in trunk under scripts/autoroutes.py
to use it

cp scripts/autoroutes.py routes.py

then edit routes.conf

as explained below:
> http://domain1.com/indexwill be mapped into  /app1/default/indexhttp://domain2.com/indexwill be mapped into  /app2/default/index
>
> It is safe in that it preserves admin, appadmin, static files,
> favicon.ico and robots.txt.
>
> http://domain1.com/favicon.icohttp://domain1.com/robots.txthttp://domain1.com/admin/...   /admin/...http://domain1.com/appadmin/...  /app1/appadmin/...http://domain1.com/static/...  /app1/static/...

Tom Atkins

unread,
Oct 18, 2010, 3:01:52 AM10/18/10
to web...@googlegroups.com
Fantastic - thanks Massimo.  That is extremely useful - my regex skills are pretty poor but this really helps with getting to grips with routes.py.

Love the 'tips of the day' - keep 'em coming!

Albert Abril

unread,
Oct 18, 2010, 3:52:32 AM10/18/10
to web...@googlegroups.com
Wow! Thank you Massimo. 
Just now I was having that problem.

Michele Comitini

unread,
Oct 18, 2010, 3:58:33 AM10/18/10
to web...@googlegroups.com
WoW :D

2010/10/18 Albert Abril <albert...@gmail.com>:

VP

unread,
Oct 18, 2010, 10:02:12 PM10/18/10
to web2py-users
thank you. I think many of us can use this tip. Many of these tips
should be archived somewhere.

Martin.Mulone

unread,
Oct 19, 2010, 6:14:56 AM10/19/10
to web2py-users
Great tip!. This is very usefull! and you make it in trunk :D
> http://domain1.com/indexwill be mapped into  /app1/default/indexhttp://domain2.com/indexwill be mapped into  /app2/default/index
>
> It is safe in that it preserves admin, appadmin, static files,
> favicon.ico and robots.txt.
>
> http://domain1.com/favicon.icohttp://domain1.com/robots.txthttp://domain1.com/admin/...   /admin/...http://domain1.com/appadmin/...  /app1/appadmin/...http://domain1.com/static/...  /app1/static/...

VP

unread,
Oct 24, 2010, 2:18:50 PM10/24/10
to web2py-users
Can Massimo or someone clarify if this tip will result in web2py
serving static files or Apache serving static files?

Is this a "production" (high-performance) set up? The assumption "one
domain per app" appears to suggest that this is a production set up.
Yet, Massimo mentioned in an early tip similar to this that web2py
would be serving static files, and is thus not meant for production.


Can someone clarify please?


Thank you.


On Oct 17, 9:03 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> http://domain1.com/indexwill be mapped into  /app1/default/indexhttp://domain2.com/indexwill be mapped into  /app2/default/index
>
> It is safe in that it preserves admin, appadmin, static files,
> favicon.ico and robots.txt.
>
> http://domain1.com/favicon.icohttp://domain1.com/robots.txthttp://domain1.com/admin/...   /admin/...http://domain1.com/appadmin/...  /app1/appadmin/...http://domain1.com/static/...  /app1/static/...

mdipierro

unread,
Oct 24, 2010, 2:25:00 PM10/24/10
to web2py-users
This assumes web2py is serving static files. But it does not prevent
you to use a apache for it.
In this case you would need the virtual hosts for the different apps.
> >http://domain1.com/indexwillbe mapped into  /app1/default/indexhttp://domain2.com/indexwillbe mapped into  /app2/default/index
>
> > It is safe in that it preserves admin, appadmin, static files,
> > favicon.ico and robots.txt.
>
> >http://domain1.com/favicon.icohttp://domain1.com/robots.txthttp://dom......   /admin/...http://domain1.com/appadmin/...  /app1/appadmin/...http://domain1.com/static/...  /app1/static/...

VP

unread,
Oct 24, 2010, 5:39:53 PM10/24/10
to web2py-users
Massimo,
Can you please show us more specifically how to do this? (I think
someone also asked the same question in a previous topic).

Thanks.
> > >http://domain1.com/indexwillbemapped into  /app1/default/indexhttp://domain2.com/indexwillbemapped into  /app2/default/index

mdipierro

unread,
Oct 24, 2010, 6:12:17 PM10/24/10
to web2py-users
Assuming you have the routes described above and this in routes.conf

----- BEGIN routes.conf-------
domain1.com /app1/default
domain2.com /app2/default
----- END ----------

you would need this in apache config file:

<VirtualHost *.domain1.com:
80>
WSGIDaemonProcess web2py user=www-data group=www-
data
WSGIProcessGroup
web2py
WSGIScriptAlias / /home/www-data/web2py/
wsgihandler.py

<Directory /home/www-data/
web2py>
AllowOverride
None
Order
Allow,Deny
Deny from
all
<Files
wsgihandler.py>
Allow from
all
</
Files>
</
Directory>

AliasMatch ^/static/(.*)
\
/home/www-data/web2py/applications/app1/static/
$1
<Directory /home/www-data/web2py/applications/app1/static/
>
Options -
Indexes
Order
Allow,Deny
Allow from
all
</
Directory>

<Location /
admin>
Deny from
all
</
Location>

<LocationMatch ^/
appadmin>
Deny from
all
</
LocationMatch>

CustomLog /var/log/apache2/access.log
common
ErrorLog /var/log/apache2/
error.log
</VirtualHost>


<VirtualHost *.domain2.com:
80>
WSGIDaemonProcess web2py user=www-data group=www-
data
WSGIProcessGroup
web2py
WSGIScriptAlias / /home/www-data/web2py/
wsgihandler.py

<Directory /home/www-data/
web2py>
AllowOverride
None
Order
Allow,Deny
Deny from
all
<Files
wsgihandler.py>
Allow from
all
</
Files>
</
Directory>

AliasMatch ^/static/(.*)
\
/home/www-data/web2py/applications/app2/static/
$1
<Directory /home/www-data/web2py/applications/app2/static/
>
Options -
Indexes
Order
Allow,Deny
Allow from
all
</
Directory>

<Location /
admin>
Deny from
all
</
Location>

<LocationMatch ^/
appadmin>
Deny from
all
</
LocationMatch>

CustomLog /var/log/apache2/access.log
common
ErrorLog /var/log/apache2/
error.log
</VirtualHost>
> > > >http://domain1.com/indexwillbemappedinto  /app1/default/indexhttp://domain2.com/indexwillbemappedinto  /app2/default/index

VP

unread,
Oct 24, 2010, 9:06:08 PM10/24/10
to web2py-users
Thank you Massimo. Your script as is didn't work for me (I use debian
lenny). Apache complained about not recognizing virtual hosts and
that there was a duplicate of the wgsi deamon (I suppose only one
deamon should be named web2py). I had to modify it to make it work.
(But still not desirable, more on this later). In case, this might
be helpful to others, here's my Apache's configuration:

(Note, I run the daemon process using myaccount not as www-data; this
deviates from the official web2py suggestion)

<VirtualHost *:80>
WSGIDaemonProcess web2py user=myaccount group=myaccount \
display-name=%{GROUP}
WSGIProcessGroup web2py
WSGIScriptAlias / /home/myaccount/web2py/wsgihandler.py

<Directory /home/myaccount/web2py>
AllowOverride None
Order Allow,Deny
Deny from all
<Files wsgihandler.py>
Allow from all
</Files>
</Directory>

<Location /admin>
Deny from all
</Location>

<LocationMatch ^/appadmin>
Deny from all
</LocationMatch>

CustomLog /var/log/apache2/access.log common
ErrorLog /var/log/apache2/error.log
</VirtualHost>


Now for each app and domain name, I have one of these:

<VirtualHost *:80>
ServerName *.mydomain.com
ServerAlias *.mydomain.com

AliasMatch ^/static/(.*) \
/home/myaccount/web2py/applications/app/static/$1

<Directory /home/myaccount/web2py/applications/app/static/>
Options -Indexes
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>



This seems to work for me. One caveat is that I can access the other
apps from any of the domains.



VP

unread,
Oct 24, 2010, 10:02:43 PM10/24/10
to web2py-users
What works is that http://domain1.com will map to app1 as intended.

What doesn't work is that app1/default/f/a/b is not mapped to f/a/b or
vice versa. This is ugly.

Can you show me how to get rid of "app1/default"?

Thanks.

mdipierro

unread,
Oct 24, 2010, 10:38:45 PM10/24/10
to web2py-users
The messages that starts the thread explains that. I tried and it
works.

On Oct 24, 9:02 pm, VP <vtp2...@gmail.com> wrote:
> What works is thathttp://domain1.comwill map to app1 as intended.

VP

unread,
Oct 24, 2010, 11:51:52 PM10/24/10
to web2py-users
Update:

if the function has no arguments, it works. I.e. http://domain.com/app/default/f
gets mapped correctly to http://domain.com/f

But if the function has arguments, it did not work for me. I.e
http://domain.com/app/default/g/a/b does not get mapped to http://domain.com/g/a/b

PS:
I got the script from here: http://web2py.googlecode.com/hg/scripts/autoroutes.py
as far as I can tell, it's the same as the one in this this thread.

mdipierro

unread,
Oct 25, 2010, 12:04:57 AM10/25/10
to web2py-users
Aha! My mistake. $a should have been $anything everywhere in the
code.

I fixed is and re-posted in trunk now under scripts/autoroutes.py

Massimo


On Oct 24, 10:51 pm, VP <vtp2...@gmail.com> wrote:
> Update:
>
> if the function has no arguments, it works.  I.e.  http://domain.com/app/default/f
> gets mapped correctly tohttp://domain.com/f
>
> But if the function has arguments, it did not work for me.   I.ehttp://domain.com/app/default/g/a/bdoes not get mapped tohttp://domain.com/g/a/b

VP

unread,
Oct 25, 2010, 12:19:13 AM10/25/10
to web2py-users
Great. It appears to be working as intended now. Thanks.

mdipierro

unread,
Oct 25, 2010, 12:44:30 AM10/25/10
to web2py-users
:-)

Bruno Rocha

unread,
Nov 28, 2010, 6:03:07 PM11/28/10
to web...@googlegroups.com
HI, I am trying to use autoroutes for the firsttime, what I want is my site running in 127.0.0.1:8080/index instead of 127.0.0.1/app/default/index.

I tried the autoroutes and routes.conf explained here but i did't figure out how to make the access to static files to work.

I am using web2py 1.89.5 all functions as /index is working well, but my static files are unreachable.

127.0.0.1:8080/index works ok, but show no images that I included with <img src=URL('static','image.png')>


My routes.conf is

----START CODE ----
127.0.0.1 /blouweb/default
---END CODE ----

My routes.py is

---START CODE---

try: config=open('routes.conf','r').read()
except: config=''

def auto_in(apps):
    routes=[
        ('/robots.txt','/blouweb/static/robots.txt'),
        ('/favicon.ico','/blouweb/static/favicon.ico'),
        ('/admin$anything','/admin$anything'),
        ]
    for a,b in [x.strip().split() for x in apps.split('\n') if x.strip() and not x.strip().startswith('#')]:
        if not b.startswith('/'): b='/'+b
        if b.endswith('/'): b=b[:-1]
        app = b.split('/')[1]
        routes+=[
            ('.*:https?://(.*\.)?%s:$method /' % a,'%s' % b),
            ('.*:https?://(.*\.)?%s:$method /static/$anything' % a,'%s/static/$anything' % app),
            ('.*:https?://(.*\.)?%s:$method /appadmin/$anything' % a,'%s/appadmin/$anything' % app),
            ('.*:https?://(.*\.)?%s:$method /$anything' % a,'%s/$anything' % b), 
            ]
    return routes

def auto_out(apps):
    routes=[]
    for a,b in [x.strip().split() for x in apps.split('\n') if x.strip() and not x.strip().startswith('#')]:
        if not b.startswith('/'): b='/'+b
        if b.endswith('/'): b=b[:-1]
        app = b.split('/')[1]
        routes+=[
            ('%s/static/$anything' % app,'/static/$anything'),
            ('%s/appadmin/$anything' % app, '/appadmin/$anything'),
            ('%s/$anything' % b, '/$anything'),
            ]
    return routes

routes_in=auto_in(config)
routes_out=auto_out(config)
---END CODE ---

Johann Spies

unread,
Feb 16, 2011, 9:13:17 AM2/16/11
to web...@googlegroups.com
On 29 November 2010 01:03, Bruno Rocha <rocha...@gmail.com> wrote:
HI, I am trying to use autoroutes for the firsttime, what I want is my site running in 127.0.0.1:8080/index instead of 127.0.0.1/app/default/index.

I tried the autoroutes and routes.conf explained here but i did't figure out how to make the access to static files to work.

I am using web2py 1.89.5 all functions as /index is working well, but my static files are unreachable.

Could you solve this problem about the static files?

Regards
Johann
--
 May grace and peace be yours in abundance through the full knowledge of God and of Jesus our Lord!  His divine power has given us everything we need for life and godliness through the full knowledge of the one who called us by his own glory and excellence.
                                                    2 Pet. 1:2b,3a

Bruno Rocha

unread,
Feb 16, 2011, 10:35:33 AM2/16/11
to web...@googlegroups.com

Johann Spies

unread,
Feb 17, 2011, 1:47:50 AM2/17/11
to web...@googlegroups.com
On 16 February 2011 17:35, Bruno Rocha <rocha...@gmail.com> wrote:
Thanks. It is about the same as mine.  I was just wondering whether my jqgrid-problem (another thread) on my production server was related to the problem you  reported.

Regards
Johann

Bruno Rocha

unread,
Feb 17, 2011, 6:35:28 AM2/17/11
to web...@googlegroups.com
jqgrig, plugin_wiki or any other plugin which has a controller can't work with this autoroutes, because in autotoures we define a default controller in this case 'default.py' is the controller. any request with 'domain.com/action' will try to find this action inside default.py, but plugin_wiki and jqgrid has its own controllers. 

perhaps it can work if you take every action from controllers/plugin_jqgrid.py and paste it in default.py, needs to fix absolute urls too.

I dont know if we can, neither how to define multiple controllers in autoroutes.




2011/2/17 Johann Spies <johann...@gmail.com>

Nguyen Minh Tuan

unread,
Jun 22, 2014, 10:34:22 PM6/22/14
to web...@googlegroups.com
Hi Massimo,

I think there is error in your script :

CURRENT line 69 :
('.*:https?://(.*\.)?%s:$method /$anything' % domain, '%s/$anything' % path)

should be :
('.*:https?://(.*\.)?%s:$method /%s/$anything' % (domain, app), '/%s/$anything' % app)

Regards,
Tuan

Massimo Di Pierro

unread,
Jun 23, 2014, 12:51:03 AM6/23/14
to web...@googlegroups.com
Can you post the complete correct script? thanks.

lyn2py

unread,
Jul 1, 2014, 9:25:12 AM7/1/14
to web...@googlegroups.com
I don't know how I missed this, but these routes are working very well and very stable on production server. 

Thanks Massimo for sharing the great tip!

lyn2py

unread,
Jul 3, 2014, 8:04:44 AM7/3/14
to web...@googlegroups.com
I have a question for anyone using this… I realized that it only works for redirects to the functions within default.py. If I setup another controller, it can't route to that controller. Is this the intended behaviour? How can I include other controllers without having to add one controller for every line? Thanks :)

Massimo Di Pierro

unread,
Jul 3, 2014, 10:51:22 AM7/3/14
to web...@googlegroups.com
There is nothing "default" specific in the script. Something else must be the problem.

Nguyen Minh Tuan

unread,
Jul 3, 2014, 9:59:37 PM7/3/14
to web...@googlegroups.com
Hi Massimo,

Lyn2py posted above is that issue I met, I post complete script :
(I mark the only one line I changed with red color)

-------------- routes.py ---------------------------
config = '''
site1.com.vn /hhp/default
site2.com.vn /welcome/default
'''

def auto_in(apps):
    routes = [
        ('/admin$anything', '/admin$anything'),
    ]
    for domain, path in [x.strip().split() for x in apps.split('\n') if x.strip() and not x.strip().startswith('#')]:
        if not path.startswith('/'):
            path = '/' + path
        if path.endswith('/'):
            path = path[:-1]
        app = path.split('/')[1]
        routes += [
            ('.*:https?://(.*\.)?%s:$method /' % domain, '%s' % path),
            ('.*:https?://(.*\.)?%s:$method /static/$anything' % domain, '/%s/static/$anything' % app),
            ('.*:https?://(.*\.)?%s:$method /appadmin/$anything' % domain, '/%s/appadmin/$anything' % app),
            ('.*:https?://(.*\.)?%s:$method /%s/$anything' % (domain, app), '/%s/$anything' % app)
        ]
    return routes


def auto_out(apps):
    routes = []
    for domain, path in [x.strip().split() for x in apps.split('\n') if x.strip() and not x.strip().startswith('#')]:
        if not path.startswith('/'):
            path = '/' + path
        if path.endswith('/'):
            path = path[:-1]
        app = path.split('/')[1]
        routes += [
            ('/%s/static/$anything' % app, '/static/$anything'),
            ('/%s/appadmin/$anything' % app, '/appadmin/$anything'),
            ('/%s/$anything' % path, '/$anything')
        ]
    return routes

routes_in = auto_in(config)
routes_out = auto_out(config)
---------------------------------------------------

Regards,
Tuan.


--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/8KxcHTRIBWU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

lyn2py

unread,
Jul 4, 2014, 10:45:33 PM7/4/14
to web...@googlegroups.com
Hi Tuan I will try your modification when I get back to my terminal and post back on the results.

lyn2py

unread,
Jul 5, 2014, 3:33:32 AM7/5/14
to web...@googlegroups.com
Hi Tuan, 

I tried the change (line in red) but it couldn't route to my app properly. I'm not familiar with the regex routes, so I'm using it as-is. I don't know how to troubleshoot this.

lyn2py

unread,
Jul 5, 2014, 3:43:25 AM7/5/14
to web...@googlegroups.com
In using this routes.py, cannot have the word "admin" within the function. Not sure why that is so, but it breaks the routes and generates an "Invalid Request". This was my issue:

https://groups.google.com/forum/#!topic/web2py/2GyztlR-ZYI

In addition, I am unable to use more than the default.py controller. Additional controllers unable to route. Error message is "

invalid function (default/some_other_controller)"


Thanks.

Nguyen Minh Tuan

unread,
Jul 6, 2014, 9:43:29 PM7/6/14
to web...@googlegroups.com
Hi Lyn2py, can you send your script?
Reply all
Reply to author
Forward
0 new messages