-
Notifications
You must be signed in to change notification settings - Fork 4
Routing
Once you've created a server object (via createServer
), you can being adding routes. The server object exposes 7 functions you can use to add routes. These functions map to HTTP methods, they are:
- GET
- HEAD
- POST
- PUT
- DELETE
- OPTIONS
- NON_REST (can be used for things like socket.io channels)
To create a route, we might do something like the following:
server.GET('/api/clients')
This creates (or retrieves if one was already created) a route for any GET requests to '/api/client'. You can request a route multiple times to add further configuration if desired. This route isn't particularly useful right now because we haven't configured it. Before we go into configuring however lets take a look at the route construction rules.
Routes may contain any valid URL character. 2 characters are reserved for special use, these are :
and *
.
The :
at the beginning of a route component (the parts between the /) indicates a URL variable. Any value matches this, but only if the rest of the non-variable matches. For example the route /client/:clientId/files
matches /client/15/files
and /client/paysOnTime/files
but not /client/15/bills
because bills
does not match files
.
The *
as the only element in a route component indicates a wildcard. Beyond this point, anything present matches. It should only be used in the last position of your route. A correct wildcard usage is /courses/math101/assignments/*
while /courses/math101/assignments/*/file
would be incorrect because /file
appears after the *
component. Anything beyond the * is available as server.CONSTANTS.URL_VAR_WILDCARD
(we'll see how to use this later).
When selecting a route, the router always prefers specific matches to generic matches. Imagine we have the following routes:
1: /clients/:clientId/bills
2: /clients/:clientId/*
3: /clients/15/bills
Note that the order of declaration of the routes is not relevant to how routes are looked up. These routes could appear in any order and the lookup results would be identical. In this case if the user navigated to /clients/15/bills
, even though it passes all the routes, route 3 would be selected. The reason for this is that it's the most specific route possible. In the event that the user navigated to /clients/22/bills
route 1 would be selected, and so on.
Now that we know the construction rules, we can make our routes do something. To do this, we'll wait for the route to be configurable and then configure it. Lets take a look at what that would look like:
server.GET('/api/clients/').onValue(function (route) {
});
Notice the onValue
after the GET
. This is because GET
(and in fact all route functions) returns a Bacon.js stream. If you're unfamiliar with Bacon.js or with streams, that's ok. Just think of it as a high powered promise. Once our route is ready, our function will be executed and the route will be passed to it.
Inside the configuration function, the route object exposes 3 main methods: inject
, when
and render
.
The inject
method enables the "injection" of values into a route. This allows you to add things to a route like database connections, global config objects, etc. Inject takes an object, breaks it into parts and makes it available to functions when they are run (see the section on the when block for details. An example of injecting a value might be:
route.inject({maxAttempts: 10});
There are 2 caveats to injecting values into a route. First, any value injected is a constant (you can not replace the injected value inside the route). Second, due to the internal workings of FRHTTP, if you use Bacon.js, you can not directly inject a Bacon observable. As a workaround you can wrap the observable in a function and inject the function.
inject
is chainable and returns a route object.
The when
method takes a when definition object described in detail here.
The render
method takes a render definition object described in detail here.
Docs
Tutorials