05: router

What’s a router?

05_router
Author

Kennedy Mwavu

Published

July 10, 2024

Run app

  1. cd into the 05_router/ dir:

    cd 05_router/
    • There are 2 directories there: box/ & r_pkg_structure/.

    • cd into any of them, say, r_pkg_structure/:

      cd r_pkg_structure/
  2. Fire up R:

    R
  3. Restore package dependencies:

    renv::restore()

    Once done, exit R.

  4. server.R is the entry point. To start the app, run this on the terminal:

    Rscript index.R

Explanation

This app starts a server and listens on port 3000 for connections.

It has two endpoints:

  • /api/members
  • /api/members/:id

Routing refers to how an application’s endpoints (URIs) respond to client requests.

For an introduction to routing, see 03_basic_routing.

If you look at 04_simple_json_api you’ll notice that the routes we created all belong to /api/members and we kept repeating that base/root route.

Wouldn’t it be nice to only have to use / and /:id and have ambiorix prepend the /api/members automatically?

That would give you a better app structure making it manageable.

Enter ambiorix::Router().

Use the ambiorix::Router class to create modular, mountable router handlers.

A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.

Using the example 04_simple_json_api, this is how we would transform it:

# members.R
members_router <- \() {
  router <- Router$new("/members")

  # get all members:
  router$get("/", \(req, res) {
    # ...
  })

  # get a single member:
  router$get("/:id", \(req, res) {
    # ...
  })

  # create a new member:
  router$post("/", \(req, res)) {
    # ...
  }

  # update member:
  router$put("/:id", \(req, res) {
    # ...
  })

  # delete member:
  router$delete("/:id", \(req, res) {
    # ...
  })

  router
}

The server.R file would now be:

library(ambiorix)

# <bring/import the members.R file>

PORT <- 3000

app <- Ambiorix$new()

# mount the router:
app$use(members_router())

app$start(port = PORT, open = FALSE)

Keep this in mind:

Ambiorix is unopinionated. As such, it is up to you to decide how you want to bring/export the members.R file into index.R.

Some options are:

  • Use box (Highly recommended, ⭐⭐⭐⭐⭐) especially if you develop large apps/systems, for two reasons:
    1. Allows nested files, folders & modules (a big win)
    2. Explicit name imports ie. you’re almost always sure from which package a function is from.
  • Use R package structure (Recommended, ⭐⭐⭐⭐). Will not allow nested folders but will work really well for small to medium apps.
  • source() files (NOT recommended, 1⭐). Haha. Iykyk.

Choose wisely.

Multiple routers

Learn how you can mount ✨multiple routers✨.