Updated to 1.9
Since uWSGI 1.9, a programmable internal routing subsystem is available (older releases since 1.1 have a less featureful version).
You can use the internal routing subsystem to dynamically alter the way requests are handled. For example you can use it to trigger a 301 redirect on specific URLs, or to serve content from the cache on specific conditions.
The internal routing subsystem is inspired by Apache’s mod_rewrite and Linux’s iptables command.
Please, before blasting it for being messy, not-elegant nor Turing-complete, remember that it must be FAST and only FAST. If you need elegance and more complexity, do that (more slowly) in your code.
The internal routing table is a sequence of ‘’rules’’ executed one after another (forward jumps are allowed too).
Each rule is composed by a ‘’subject’‘, a ‘’condition’’ and an ‘’action’‘
The ‘’condition’’ is generally a PCRE regexp applied to the subject, if it matches the action is triggered. Subjects are request’s variables.
Currently the following subjects are supported:
In addition to this, a pluggable system of lower-level conditions is available.
You can access this system using the --route-if option.
Currently the following checks are supported:
When a check requires a pattern (like with ‘equal’ or ‘regexp’) you split it from the subject with a semicolon:
; never matches
route-if = equal:FOO;BAR log:never here
; matches
route if = regexp:FOO;^F log:starts with F
Actions are the functions to run if a rule matches. This actions are exported by plugins and have a return value.
Each action has a return value which tells the routing engine what to do next.
The following return codes are supported:
When a rule does not match, NEXT is assumed.
[uwsgi]
route-user-agent = .*curl.* redirect:http://uwsgi.it
route-remote-addr = ^127\.0\.0\.1$ break:403 Forbidden
route = ^/test log:someone called /test
route = \.php$ rewrite:/index.php
route = .* addheader:Server: my uWSGI server
route-host = ^localhost$ logvar:local=1
route-uri = ^/foo/(.*)\.jpg$ cache:key=$1.jpg
route-if = equal:${PATH_INFO};/bad break:500 Internal Server Error
The previous rules, build the following table:
In addition to PCRE placeholders/groups (using $1 to $9) you can access request variables (PATH_INFO, SCRIPT_NAME, REQUEST_METHOD...) using the ${VAR} syntax.
[uwsgi]
route-user-agent = .*curl.* redirect:http://uwsgi.it${REQUEST_URI}
route-remote-addr = ^127\.0\.0\.1$ break:403 Forbidden for ip ${REMOTE_ADDR}
You can access a cookie value using the ${cookie[name]} syntax:
[uwsgi]
route = ^/foo log:${cookie[foobar]}
this will log the content of the ‘foobar’ cookie of the current request
You can access the value of the HTTP query string using the ${qs[name]} syntax:
[uwsgi]
route = ^/foo log:${qs[foobar]}
this will log the content of the ‘foobar’ item of the current request’s query string
Both the cookie and qs vars, are so-called “routing vars”. They are pluggable, so external plugins can add new vars to add new features to your application. (Check the The GeoIP plugin plugin for an example of this.)
A number of embedded routing variables are also available.
mime – returns the mime type of the specified var: ${mime[REQUEST_URI]}
[uwsgi]
route = ^/images/(.+) addvar:MYFILE=$1.jpg
route = ^/images/ addheader:Content-Type: ${mime[MYFILE]}
time – returns time/date in various form. The only supported (for now) is time[unix] returning the epoch
math – requires matheval support. Example: math[CONTENT_LENGTH+1]
base64 – encode the specified var in base64
hex – encode the specified var in hex
uwsgi – return internal uWSGI information, uwsgi[wid] and uwsgi[pid] are currently supported
This is a good question. You just need to always remember that uWSGI is about versatility and performance. Gaining cycles is always good. The --route-if option, albeit versatile, cannot be optimized, all of its parts has to be recomputed at every request. This is obviously very fast, but --route-uri option (and friends) can be pre-optimized (during startup) to directly map to the request memory areas, so if you can use them, you definitely should. :)
Yes, the most controversial construct of the whole information technology industry (and history) is here. You can make forward (only forward!) jumps to specific points of the internal routing table. You can set labels to mark specific point of the table, or if you are brave (or foolish) jump directly to a rule number (rule numbers are printed on server startup, but please use labels...)
[uwsgi]
route-host = ^localhost$ goto:localhost
route-host = ^sid\.local$ goto:sid.local
route = .* last:
route-label = sid.local
route-user-agent = .*curl.* redirect:http://uwsgi.it
route-remote-addr = ^192\.168\..* break:403 Forbidden
route = ^/test log:someone called /test
route = \.php$ rewrite:/index.php
route = .* addheader:Server: my sid.local server
route = .* logvar:local=0
route-uri = ^/foo/(.*)\.jpg$ cache:key=$1.jpg
route = .* last:
route-label = localhost
route-user-agent = .*curl.* redirect:http://uwsgi.it
route-remote-addr = ^127\.0\.0\.1$ break:403 Forbidden
route = ^/test log:someone called /test
route = \.php$ rewrite:/index.php
route = .* addheader:Server: my uWSGI server
route = .* logvar:local=1
route-uri = ^/foo/(.*)\.jpg$ cache:key=$1.jpg
route = .* last:
The example is like the previous one, but we make tiny differences between domains. Check the use of “last:”, to interrupt the routing table scan.
Obviously (or not?) you can rewrite the first 2 rules as one:
[uwsgi]
route-host = (.*) goto:$1
Return value: CONTINUE
Stop the scanning of the internal routing table and continue to the selected request handler.
Return value: BREAK
Stop scanning the internal routing table and close the request. Can optionally returns the specified HTTP status code:
[uwsgi]
route = ^/notfound break:404 Not Found
route = ^/bad break:
route = ^/error break:500
Return value: NEXT
Print the specified message in the logs.
[uwsgi]
route = ^/logme/(.) log:hey i am printing $1
Return value: NEXT
Add the specified CGI (environment) variable to the request.
[uwsgi]
route = ^/foo/(.) addvar:FOOVAR=prefix$1suffix
Return value: NEXT
Add the specified HTTP header to the response.
[uwsgi]
route = ^/foo/(.) addheader:Foo: Bar
Return value: NEXT
Remove the specified HTTP header from the response.
[uwsgi]
route = ^/foo/(.) delheader:Foo
Return value: NEXT
Extremely advanced (and dangerous) function allowing you to add raw data to the response.
[uwsgi]
route = ^/foo/(.) send:destroy the world
Return value: NEXT
Extremely advanced (and dangerous) function allowing you to add raw data to the response, suffixed with rn.
[uwsgi]
route = ^/foo/(.) send-crnl:HTTP/1.0 100 Continue
Return value: BREAK
Plugin: router_redirect
Return a HTTP 302 Redirect to the specified URL.
Return value: BREAK
Plugin: router_redirect
Return a HTTP 301 Permanent Redirect to the specified URL.
Return value: NEXT
Plugin: router_rewrite
A rewriting engine inspired by Apache mod_rewrite. Rebuild PATH_INFO and QUERY_STRING according to the specified rules before the request is dispatched to the request handler.
[uwsgi]
route-uri = ^/foo/(.*) rewrite:/index.php?page=$1.php
Alias for rewrite but with a return value of CONTINUE, directly passing the request to the request handler next.
Return value: BREAK
Plugin: router_uwsgi
Rewrite the modifier1, modifier2 and optionally UWSGI_APPID values of a request or route the request to an external uwsgi server.
[uwsgi]
route = ^/psgi uwsgi:127.0.0.1:3031,5,0
This configuration routes all of the requests starting with /psgi to the uwsgi server running on 127.0.0.1:3031 setting modifier1 to 5 and modifier2 to 0.
If you only want to change the modifiers without routing the request to an external server, use the following syntax.
[uwsgi]
route = ^/psgi uwsgi:,5,0
To set a specific UWSGI_APPID value, append it.
[uwsgi]
route = ^/psgi uwsgi:127.0.0.1:3031,5,0,fooapp
The subrequest is async-friendly (engine like gevent, or ugreen are supported) and if offload threads are available they will be used.
Return value: BREAK
Plugin: router_http
Route the request to an external HTTP server.
[uwsgi]
route = ^/zope http:127.0.0.1:8181
You can substitute an alternative Host header with the following syntax:
[uwsgi]
route = ^/zope http:127.0.0.1:8181,myzope.uwsgi.it
Return value: BREAK
Plugin: router_static
Serve a static file from the specified physical path.
[uwsgi]
route = ^/logo static:/var/www/logo.png
Return value: NEXT or BREAK 401 on failed authentication
Plugin: router_basicauth
Four syntaxes are supported.
Example:
[uwsgi]
route = ^/foo basicauth-next:My Realm,foo:bar
route = ^/foo basicauth:My Realm,foo2:bar2
route = ^/bar basicauth:Another Realm,kratos:
Example: using basicauth for Trac
[uwsgi]
; load plugins (if required)
plugins = python,router_basicauth
; bind to port 9090 using http protocol
http-socket = :9090
; set trac instance path
env = TRAC_ENV=myinstance
; load trac
module = trac.web.main:dispatch_request
; trigger authentication on /login
route = ^/login basicauth-next:Trac Realm,pippo:pluto
route = ^/login basicauth:Trac Realm,foo:bar
;high performance file serving
static-map = /chrome/common=/usr/local/lib/python2.7/dist-packages/trac/htdocs
same as basicauth but returns NEXT on failed authentication.
Return value: NEXT or BREAK 401 on failed authentication
Plugin: ldap
This auth router is part of the LDAP plugin, so it has to be loaded in order for this to be available. It’s like the basicauth router, but uses an LDAP server for authentication, syntax: ldapauth:realm,options
Available options:
Example:
route = ^/protected ldapauth:LDAP auth realm,url=ldap://ldap.domain.com;basedn=ou=users,dc=domain;binddn=uid=proxy,ou=users,dc=domain;bindpw=password;loglevel=1;filter=(objectClass=posixAccount)
Same as ldapauth but returns NEXT on failed authentication.
The “rpc” routing instruction allows you to call uWSGI RPC functions directly from the routing subsystem and forward their output to the client.
[uwsgi]
http-socket = :9090
route = ^/foo addheader:Content-Type: text/html
route = ^/foo rpc:hello ${REQUEST_URI} ${HTTP_USER_AGENT}
route = ^/bar/(.+)$ rpc:test $1 ${REMOTE_ADDR} uWSGI %V
route = ^/pippo/(.+)$ rpc:test@127.0.0.1:4141 $1 ${REMOTE_ADDR} uWSGI %V
import = funcs.py
Plugin: rpc
Plugin: rpc
rpcret calls the specified rpc function and uses its return value as the action return code (next, continue, goto, etc)
Plugin: rpc
rpcnext/rpcblob calls the specified RPC function, sends the response to the client and continues to the next rule.
Plugin: rpc
In development...
In development...
See also
See also
See also
Plugin: cgi
Plugin: cgi
Plugin: router_access
Plugin: router_cache
Plugin: router_cache
Plugin: router_cache
Plugin: router_cache
Plugin: router_cache
Plugin: router_cache
Plugin: router_http
Plugin: router_memcached
Plugin: router_memcached
Plugin: router_uwsgi