Dispatcher

Overview

Routing requests is one of the most important aspects in each web service. Two primary reasons, having access control to the server content and providing user-friendly URLs.

e_dispatcher has both of them.

In order to provide URL mapping - the view/controller uses the dispatcher configuration file (dispatch.conf). This file (placed within the ../config directory) is read during the start of the application.

After making any change inside dispatch.conf, or configuration files included in it, you will need to force the dispatcher to reload its routing table. It can be accomplished by typing:

e_dispatcher:reinstall().

There are two subdirectories for pages, ../docroot and ../templates.

The ../docroot directory is public. By public, it can be accessible directly from the browser without any interaction with the framework, apart from the dispatcher.

In short, this means the whole of the ../docroot contents can be downloaded at once, depending on your web server configuration. If you allow the disk directories to be displayed, then many tools, like cURL, can download the contents of ../docroot with one command. Depending on your situation, this may be quite advantageous.

One immediate advantage is placing images, video, CSS, Javascript, etc. within the ../docroot directory as all of these items have no need to be evaluated at all. They are simply used as is. Any other files that meet the 'serve-as-is' qualification can be placed in the ../docroot directory as well. Additionally, if you do not want any of the Erlang web wpart(s) to be expanded, they too can be placed in ../docroot and the contents will be served without any translation.

If file security is a concern, you may add directories below ../docroot and they can be secured through dispatcher configuration.

../templates is used for static pages that use a template and for dynamic pages.

Regular Expressions

Erlang Web uses the standard Erlang/OTP 're' module for regular expression evaluation. A summary of 'Regexp' is below or a detailed description of the syntax and semantics of the meta-characters can be obtained at:

 http://www.erlang.org/doc/man/re.html#sect2

The rules you create in the dispatcher deal with URLs and NOT filenames. One thing to keep in mind is that rules start with a / as per the HTTP RFC specification. Every entry in dispatch.conf that anchors the Regexp at the beginning must start with / and anything else is incorrect.

Note that since the 1.3 release, e_dispatcher is also capable of reverse dispatching.

Dispatching types

There are two basic types of dispatching: static and dynamic.

Static dispatching

Static dispatching has been designed for accessing the content which doesn’t need to be generated for a request (which is static). Files can be served directly as they are (examples include media, images and CSS). All without inspecting the content and/or changing the access path.

Or you can point to the template which needs expanding.

In both of these cases the controller is not accessed at all. You may not server dynamic content from within a static page. When you define the static entry in the dispatcher, {static,Regexp,Target), you must know the target filename for the request, and whether it is a template or located in ../docroot.

Dynamic dispatching

This involves the controller handling the URL requests. The URL the client enters into their browser is sent to the controller function. This allows content to be created on demand. In other word, perform access control, retrieve data from a database, create a web page, and validate input data would be examples of dynamic content. In short, the page could change with each client request. This includes redirecting the client to a different URL or using a different template.

Flow Control

The evaluation order of the dispatcher entries is as follows:

dispatch.conf

The dispatch.conf file is placed under the ../config directory and is the one of the must-have files in your system. It consists of Erlang tuples which tell the dispatcher how to handle the incoming requests.

Each entry contains a regular expression element - the dispatcher checks if it matches the requested URL.

The first matching entry will be used to handle the requested URL.

The following types of entries are allowed inside the dispatch.conf file:

Yes, there is a trailing period “.” at the end of each entry and it is needed.

Regular Expression Meta Character Summary

Regular Expressions within dispatch.conf

While this is not intended to be a tutorial on regular expressions (Regexp), there is enough information here to get you grounded in the use of dispatch.conf and how it applies to you.

{static, Regexp, File}.
{static, Regexp, enoent}.

Examining each part: {static, Regexp, File}.

Examples

This following entry could be used to serve a file with the name of index:

As a first effort, this will work. It will also match everything that has "index" keyword inside, such as:

and any other file that contains the character sequence “index”. The first file that is found will be the one that is served to the client.

This may appear confusing, as index.html was specified as the file to be served. But without placing limits on the search, any filename that has index within it and any extension qualifies.

By adding meta characters you are able to narrow the scope of the matching files.

Using the above listed meta characters, the following would be used to serve all *.gif files:

In summary, Erlang-web will go to ../docroot/images and fetch any filename.gif as needed.

To return to the index.html example above. By using the following meta characters, you can narrow your search to one specific file:

Named subpatterns

Named subpatterns is the mechanism used for extracting certain information from an input string. Using regular expressions, we are able to specify the semantics of the incoming URL and get its value. Moreover, the named subpatterns allows us to do a simple syntax validation.

The syntax is the same as in dynamic dispatcher rules, but the regular expression is modified a bit. If we want to bind some part of the input string to the given name, we should use the following syntax:

"HeadOfRegexp(?<NameOfThePattern>RegexpPart)TailOfRegexp"

When the whole regular expression matches the requested URL, it will extract its selected part and tag it with the specified name. The list of extracted values will be passed to the first function on dataflow list (if we are not using the named subpatterns mechanisms we will get the empty list there). The passed list will have format:

[{name_of_the_pattern, Value} | ...]

For example, when we run a blog and we want to display our post by entering the address /show/post/Post_no, we can do it using named subpatterns:

{dynamic, "^/blog/post/(?<post_no>[0-9]+)$", {blog, display_post}}.

When the incoming URL, let’s say /blog/post/23, could be described by the regular expression: /blog/post/[0-9]+$, the part responsible for the post number will be extracted from it. The result of the named subpatterns will be a property list:

[{post_no, "23"}]

and it will be passed to the first function on the dataflow list.

We can place more than one named subpatterns in the regular expressions, for example:

{dynamic, "^/blog/post/(?<post_no>[0-9]+)/comment/(?<comment_title>.+)$}.

for /blog/post/5/comment/first_comment URL, dispatcher will pass:

[{post_no, "5"}, {comment_title, "first_comment"}]

to the first function on the dataflow list.

Skipping the dispatcher

Sometimes our service provides a very simple API and we will not need support from the dispatcher. Moreover, re module is not as fast as a Perl equivalent, so for efficiency reasons we will decide that we want uglier URL’s instead of many regular expression matches. One last reason for providing the dispatcher omission functionality is to keep backward compatibility with the prior version of Erlang Web.

If we want to skip the dispatcher, we must prefix the URL with app/. The meaning is as follows:

http://example.org/app/Module/Function/View.part1/View.part2/.../View.partN

The call path is split with / and the Module:Function is called (of course following the dataflow rules). In case Module:Function call returns the template atom, the View will be expanded (path to the template will be created by joining the View.partN).

Example

This is a simple example of nested dispatcher configuration files:

dispatch.conf

   1   {dynamic, "^[/]*$", {main, home}}.
   2   {dynamic, "^/index.html$", {main, home}}.
   3 
   4   {dynamic, delegate, "^/user", "config/dispatcher/user.conf"}.
   5 
   6   {static, "^/about$", "about.html"}.
   7   {static, "^style.css$", enoent}.

and the included file:

user.conf

   1   {dynamic, "/create$", {users, create}}.
   2   {dynamic, "/delete$", {users, delete}}.
   3 
   4   {static, "/welcome$", "users/welcome.html"}.

The following services will be accessible on corresponding URLs:

Example

The following example shows the alias clause possibilities: dispatch.conf

   1 {dynamic, "^[/]*$", {main, home}}.
   2 {alias, "^/index\.html$", "/"}.
   3 
   4 {dynamic, "^/blog/read/(?<post_no>[0-9]+)/?$", {blog, read}}.
   5 {alias, "^/blog/(?<post_no>[0-9]+)/?$", "/blog/read/(?<post_no>)"}.

The configuration above enables two basic operations:

This case is rather simple and gives us only a little advantage - let's take a look at the second pair of rules.

The configuration above tells:

Dispatcher (last edited 2009-08-04 02:56:09 by mwillson)