Handling Multiple Routes

Source   Edit  

Goal: Learn how to handle different request paths in your HTTP server.

Source code: chapter2/src/dashboard.nim

Our first server version could only respond with one message regardless of the URL. Real-world applications usually need to handle multiple routes.

Let's update our server to handle different paths differently:

import chronos/apps/http/httpserver

#ANCHOR: handler
proc handler(
    reqfence: RequestFence
): Future[HttpResponseRef] {.async: (raises: [CancelledError]).} =
  let request = reqfence.valueOr:
    return defaultResponse()

  #ANCHOR: routing
  try:
    case request.uri.path
    of "/":
      await request.respond(Http200, "Welcome to the Status Dashboard!")
    of "/status":
      await request.respond(Http200, "The server is operational.")
    else:
      await request.respond(Http404, "Page not found.")
  except HttpWriteError:
    defaultResponse()
  #ANCHOR_END: routing

#ANCHOR_END: handler

#ANCHOR: main
proc main() {.async: (raises: [TransportAddressError, CancelledError]).} =
  let
    address = initTAddress("127.0.0.1:8080")
    server = HttpServerRef.new(address, handler).valueOr:
      echo "Unable to start HTTP server: " & error
      return

  server.start()
  echo "HTTP server running on http://127.0.0.1:8080"

  try:
    await server.join()
  finally:
    await server.stop()
    await server.closeWait()

#ANCHOR_END: main

when isMainModule:
  waitFor main()

To test the routes, run the project with nimble run and try visiting these URLs in your browser:

Routing Logic

The change is how we process the incoming request in the handler:

  try:
    case request.uri.path
    of "/":
      await request.respond(Http200, "Welcome to the Status Dashboard!")
    of "/status":
      await request.respond(Http200, "The server is operational.")
    else:
      await request.respond(Http404, "Page not found.")
  except HttpWriteError:
    defaultResponse()
  

We use a case statement to check the request.uri.path.

  • For the root path /, we return a welcome message.
  • For the /status path, we return a simple operational message.
  • For any other path, we use the else branch to return an HTTP 404 Not Found error.

By using httpserver: respond(HttpRequestRef, HttpCode, ByteChar), we can easily control both the HTTP status code and the response body.