For server and client purposes we use Pointer router. Routes are described in YAML and bundled into main api tree file as N.config.router after init. Router instanse is accessible as N.runtime.router.

Router config for the client is kept under N.runtime.client_routes.

Application Routes

Application routes are defined in router section of config files:

router:
  http.get:
    forums.list:
      "/f{forum_id}/":
        forum_id: /\d+/
      "/f{forum_id}/index({page}).html":
        forum_id: /\d+/
        page:
          match: /[2-9]|[1-9]\d+/
          default: 1

    forums.threads.show:
      "/f{forum_id}/thread{thread_id}(-{page}).html":
        forum_id: /\d+/
        thread_id: /\d+/
        page:
          match: /[2-9]|[1-9]\d+/
          default: 1

    forums.threads.redirect:
      "/f{forum_id}/thread{thread_id}-{goto}.html":
        forum_id: /\d+/
        thread_id: /\d+/
        goto: /new-post|last-post/

    search:
      "/search/": ~

All routes are splitted into groups by responders they are related. That groups may be specialized by dot-separated list of HTTP methods. In the above example there is the only responder http with get method. It means that declared routes will be served by http responder and only for GET HTTP method. Method names in the config must be lowercased. get method always implies head method as well.

NOTICE. Routes with leading # are used by clients ONLY. Not implemented yet

SECURITY WARNING. NEVER make routes, that change application state. Such actions should go via rpc, that has CSRF protection.

Route Params Options

Optional:

See example above and Pointer new Route documentation of params options.

Slugs

Routes can contain slugs. Technically, that's usual optional params.

router:
  http.get:
    faq.post.show:
      "/qa/({categoryslug}/){post_id}(-{postslug}).html": ~

The route above will match any of the following URLs:

/qa/123.html
/qa/123-pochemu-krokodil-zelyoni.html
/qa/animals/123-pochemu-krokodil-zelyoni.html

Recommended behavior for app developers is to redirect all non-full url's with 302 code. This can be done with before filter. Note, that it's a good idea to cache full url (or md5) - to avoid recalculations on every request.

CAUTION. NEVER route http methods, that posts data. That will cause CSRF vulnerability. ONCE AGAIN. Only give access to http "read" methods, that will not modify data. Posting should be done ONLY via rpc call, when user click on links, buttons, and so on.

Overrides

If you are not satisfied with defaul routes, you can wish to override those at application-level config. Any config object can have special key ~override: true. When such key found, branches from other configs will be wiped. Without this key, objects are reqursively merged.

router:
  http.get:
    forums.list:
      ~override: true
      "/forum{forum_id}/":
        page: /[01]/
        forum_id: /\d+/
    # ...

Mounting (and binding) applications

Mounting (and binding) of applications is described in bind section of config files. It has API path as key and options of it's binding as values, e.g.:

bind:
  default:
    listen: 0.0.0.0:3000

  forums:
    mount: /forum

Options are Objects of key-value pairs. All parts are optional:

HTTPS

As you can see above you can make nodeca start SSL server. Here's an example configuration that starts an https server on 443 port:

bind:
  default:
    listen: 0.0.0.0:443
    mount:  https://dev.nodeca.org
    ssl:
      key:  ./etc/server.key
      cert: ./etc/server.cert

You may also want to use stunnel for HTTPS while running nodeca application in normal mode, for this purposes you MUST NOT specify ssl option, and provide only a protocol-specific mount point:

bind:
  default:
    listen: 127.0.0.1:3000
    mount:  https://dev.nodeca.org

Generating self-signed SSLcertificate

openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr

cp server.key server.key.orig
openssl rsa -in server.key.orig -out server.key

openssl x509 -req -days 365 -in server.csr \
        -signkey server.key -out server.cert

Fallbacks

You can mount/bind any part of N.wire's server:** channel, even serve forum.posts and forum.threads by different address:port points.

When you specify mount/bind options for forum and forum.posts, the last one will use options of forum as "defaults". In this case we can describe the way of fallbacks as follows:

bind['default'] + bind['forum'] + bind['forum.posts']

Default mount/binding point

You can use default bind-level key to describe "default" fallback mount point. Options of this case are used as "defaults" for all server methods and take place, when method has no mount/bind options:

default:
  listen: 0.0.0.0:80

forum:
  mount: /forum

#
# equals to:
#

default:
  listen: 0.0.0.0:80

forum:
  listen: 0.0.0.0:80
  mount: /forum

Handling invalid hosts

There is a special case bind-level key _ for the invalid hosts handler:

bind:
  _: !!js/function |
    function (req, res) {
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('Invalid host ' + req.headers.host);
    }