Project

General

Profile

Request Router » History » Version 6

Arjen Pander, 2015-03-12 16:59

1 1 Jan Klopper
h1. The Request Router
2 1 Jan Klopper
3 4 Elmer de Looff
When a request is sent to µWeb, the first thing that needs to be made is the decision where and how to handle it. The request router is the place where this happens. The router employed in µWeb is based on regular expressions, and delegates the request to the handler associated with the first matching expression.
4 1 Jan Klopper
5 6 Arjen Pander
Before we explain everything there is to know about routes and handlers, an example of how a router would look. The example given is a very stripped down version of the handler from the @uweb_info@ example project:
6 1 Jan Klopper
7 1 Jan Klopper
<pre><code class="python">
8 1 Jan Klopper
import uweb
9 4 Elmer de Looff
from uweb.uweb_info import pages
10 1 Jan Klopper
11 1 Jan Klopper
PAGE_CLASS = pages.PageMaker
12 4 Elmer de Looff
ROUTES = (
13 4 Elmer de Looff
    ('/static/(.*)', 'Static'),
14 4 Elmer de Looff
    ('/(broken.*)', 'FourOhFour'),
15 4 Elmer de Looff
    ('/haltandcatchfire', 'MakeFail'),
16 4 Elmer de Looff
    ('/json', 'Json'),
17 4 Elmer de Looff
    ('/text', 'Text'),
18 4 Elmer de Looff
    ('/redirect/(.*)', 'Redirect'),
19 4 Elmer de Looff
    ('/OpenIDLogin', '_OpenIdInitiate'),
20 4 Elmer de Looff
    ('/OpenIDValidate', '_OpenIdValidate'),
21 4 Elmer de Looff
    ('/ULF-Challenge', '_ULF_Challenge'),
22 4 Elmer de Looff
    ('/ULF-Login', '_ULF_Verify'),
23 4 Elmer de Looff
    ('/(.*)', 'Index'))
24 4 Elmer de Looff
25 4 Elmer de Looff
uweb.ServerSetup()
26 1 Jan Klopper
</code></pre>
27 1 Jan Klopper
28 4 Elmer de Looff
In the example above, the following things happen:
29 4 Elmer de Looff
* Firstly, we import the @uweb@ package, since we need that to configure the webserver from
30 4 Elmer de Looff
* Secondly, we import the module where the class with our handling methods is defined (the @uweb.uweb_info.pages@ module).
31 4 Elmer de Looff
* @PAGE_CLASS@ is the global that holds a reference to the [[PageMaker]] subclass for your project, from where requests are handled.
32 4 Elmer de Looff
* @ROUTES@ is the global that defines the various requests that the router understands, and directs them to the (named) method of the @PAGE_CLASS@.
33 4 Elmer de Looff
* Finally, @uweb.ServerSetup()@ starts the webserver for those cases where it runs [[StandAlone]] (and does some initial setting up for when it runs using [[Apache]])
34 1 Jan Klopper
35 4 Elmer de Looff
When a request arrives, it is checked against all the defined routes. Each of the routes is a 2-tuple, with a regular expression and a method name (as string). The request URL is matched against the regular expression, and if it succeeds, the method name will be resolved on the @PAGE_CLASS@. This method will then be executed, and the router will _not_ continue searching for a next match.
36 1 Jan Klopper
37 4 Elmer de Looff
To illustrate the previous with an example request "@/haltandcatchfire@":
38 1 Jan Klopper
39 4 Elmer de Looff
# The PAGE_CLASS is instantiated into a live [[PageMaker]]
40 4 Elmer de Looff
# The first route tuple is inspected
41 4 Elmer de Looff
#* Its regex is @'/static/(.*)'@
42 4 Elmer de Looff
#* The request does *not* match the regex
43 4 Elmer de Looff
# The second route tuple is inspected
44 4 Elmer de Looff
#* Its regex is @'/(broken.*)'@
45 4 Elmer de Looff
#* The request does *not* match the regex
46 4 Elmer de Looff
# The third route tuple is inspected
47 4 Elmer de Looff
#* Its regex is @'/haltandcatchfire'@
48 4 Elmer de Looff
#* The request *matches* the regex
49 4 Elmer de Looff
#* The associated handler method name is @'MakeFail'@
50 4 Elmer de Looff
#* The method @MakeFail@ is resolved on our @PageMaker@ instance, resulting in @pages.PageMaker.MakeFail@
51 4 Elmer de Looff
#* This method is executed and its results will be sent to the client
52 4 Elmer de Looff
# Router has ended after the third inspected route
53 1 Jan Klopper
54 4 Elmer de Looff
h2. Arguments from the request string
55 1 Jan Klopper
56 4 Elmer de Looff
Oftentimes, there are parts of the request string that are needed further on in the process. While it's possible to extract these in the PageMaker methods, this is inconvenient, and the router has the means to do this. As can be seen in the router example above, some of the regular expressions have capture groups defined. These capture groups are provided to the PageMaker method as positional arguments. For example:
57 4 Elmer de Looff
58 4 Elmer de Looff
Requesting "@/user/elmer/edit/27@" on the following router:
59 4 Elmer de Looff
60 1 Jan Klopper
<pre><code class="python">
61 4 Elmer de Looff
PAGE_CLASS = blog.BlogPages
62 4 Elmer de Looff
ROUTES = (
63 4 Elmer de Looff
    ('/user/(\w*)/edit/(\d*)', 'EditArticle'),
64 4 Elmer de Looff
    ('/', 'Index'))
65 1 Jan Klopper
</code></pre>
66 1 Jan Klopper
67 4 Elmer de Looff
Will end up calling the method @blog.BlogPages.EditArticle@ with the arguments @('Elmer', '27')@. Note that all arguments are provided as strings, type-conversion is left to the developer.
68 1 Jan Klopper
69 4 Elmer de Looff
h2. Typical regexes for request matching
70 4 Elmer de Looff
71 1 Jan Klopper
How to use various other url formats:
72 1 Jan Klopper
73 4 Elmer de Looff
* To match one or more letters, numbers, dashes and spaces, use this: @'([\w\- ]+)'@
74 4 Elmer de Looff
* Match optional trailing slashes (so that requests don't end up 404'ing because of an added slash) add: @'/?'@
75 4 Elmer de Looff
* To match optional an optional page number: @'article/([\w\- ]+)/?(\d+)?'@
76 4 Elmer de Looff
** This matches @/article/cookies_are_delicious@
77 4 Elmer de Looff
** As well as @/article/cookies_are_delicious/2@
78 4 Elmer de Looff
** And also @/article/cookies_are_delicious/@ &ndash; to allow for trailing slashes that are almost certain to happen
79 5 Elmer de Looff
80 5 Elmer de Looff
h2. Unicode notice
81 5 Elmer de Looff
82 5 Elmer de Looff
Where available (and necessary), path strings will be decoded from UTF8 in the [[Request]] object. The regular expressions for the router are also evaluated with full support for Unicode. This means that a route-regex @'\w+'@ will match 'café' (the French for 'coffee'), despite the non-ASCII characters in that string.