URL
The URL
function is one of the most important functions in web2py. It generates internal URL paths for the actions and the static files.
Here is an example:
URL('f')
is mapped into
/[application]/[controller]/f
Notice that the output of the URL
function depends on the name of the current application, the calling controller, and other parameters. web2py supports URL mapping and reverse URL mapping. URL mapping allows you to redefine the format of external URLs. If you use the URL
function to generate all the internal URLs, then additions or changes to URL mappings will prevent broken links within the web2py application.
You can pass additional parameters to the URL
function, i.e., extra terms in the URL path (args) and URL query variables (vars):
URL('f', args=['x', 'y'], vars=dict(z='t'))
is mapped into
/[application]/[controller]/f/x/y?z=t
The args
attributes are automatically parsed, decoded, and finally stored in request.args
by web2py. Similarly, the vars
are parsed, decoded, and then stored in request.vars
. args
and vars
provide the basic mechanism by which web2py exchanges information with the client’s browser.
If args contains only one element, there is no need to pass it in a list.
You can also use the URL
function to generate URLs to actions in other controllers and other applications:
URL('a', 'c', 'f', args=['x', 'y'], vars=dict(z='t'))
is mapped into
/a/c/f/x/y?z=t
It is also possible to specify application, controller and function using named arguments:
URL(a='a', c='c', f='f')
If the application name a is missing the current app is assumed.
URL('c', 'f')
If the controller name c is missing, the current one is assumed.
URL('f')
Instead of passing the name of a controller function it is also possible to pass the function itself
URL(f)
For the reasons mentioned above, you should always use the URL
function to generate URLs of static files for your applications. Static files are stored in the application’s static
subfolder (that’s where they go when uploaded using the administrative interface). web2py provides a virtual ‘static’ controller whose job is to retrieve files from the static
subfolder, determine their content-type, and stream the file to the client. The following example generates the URL for the static file “image.png”:
URL('static', 'image.png')
is mapped into
/[application]/static/image.png
If the static file is in a subfolder within the static
folder, you can include the subfolder(s) as part of the filename. For example, to generate:
/[application]/static/images/icons/arrow.png
one should use:
URL('static', 'images/icons/arrow.png')
You do not need to encode/escape the args
and vars
arguments; this is done automatically for you.
By default, the extension corresponding to the current request (which can be found in request.extension
) is appended to the function, unless request.extension is html, the default. This can be overridden by explicitly including an extension as part of the function name URL(f='name.ext')
or with the extension argument:
URL(..., extension='css')
The current extension can be explicitly suppressed:
URL(..., extension=False)
Absolute urls
By default, URL
generates relative URLs. However, you can also generate absolute URLs by specifying the scheme
and host
arguments (this is useful, for example, when inserting URLs in email messages):
URL(..., scheme='http', host='www.mysite.com')
You can automatically include the scheme and host of the current request by simply setting the arguments to True
.
URL(..., scheme=True, host=True)
The URL
function also accepts a port
argument to specify the server port if necessary.
Digitally signed urls
When generating a URL, you have the option to digitally sign it. This will append a _signature
GET variable that can be verified by the server. This can be done in two ways.
You can pass to the URL function the following arguments:
hmac_key
: the key for signing the URL (a string)salt
: an optional string to salt the data before signinghash_vars
: an optional list of names of variables from the URL query string (i.e., GET variables) to be included in the signature. It can also be set toTrue
(the default) to include all variables, orFalse
to include none of the variables.
Here is an example of usage:
KEY = 'mykey'
def one():
return dict(link=URL('two', vars=dict(a=123), hmac_key=KEY))
def two():
if not URL.verify(request, hmac_key=KEY): raise HTTP(403)
# do something
return locals()
This makes the action two
accessible only via a digitally signed URL. A digitally signed URL looks like this:
/welcome/default/two?a=123&_signature=4981bc70e13866bb60e52a09073560ae822224e9
Note, the digital signature is verified via the URL.verify
function. URL.verify
also takes the hmac_key
, salt
, and hash_vars
arguments described above, and their values must match the values that were passed to the URL
function when the digital signature was created in order to verify the URL.
A second and more sophisticated but more common use of digitally signed URLs is in conjunction with Auth. This is best explained with an example:
@auth.requires_login()
def one():
return dict(link=URL('two', vars=dict(a=123), user_signature=True)
@auth.requires_signature()
def two():
# do something
return locals()
In this case the hmac_key
is automatically generated and shared within the session. This allows action two
to delegate any access control to action one
. If the link is generated and signed, it is valid; else it is not. If the link is stolen by another user, the link will be invalid.
It is good practice to always digitally sign Ajax callbacks. If you use the web2py LOAD
function, it has a user_signature
argument too that can be used for this purpose:
{{=LOAD('default', 'two', vars=dict(a=123), ajax=True, user_signature=True)}}