Skip to main content
  1. Docs/
  2. Developing Applications/

Request Routing

The request routing layer in Clace is built on top of the chi routing library. The routing is built for hypermedia exchange, so all routes are defined in terms of pages and fragments within the pages. This grouping of requests helps make it clear which API does what and provide an easy mechanism to deal with partial HTMX driven requests and full page refreshes. Simpler application might have one page with some interactions within that. Larger applications can be composed of multiple pages, each page having some interactive fragments.

Pages #

The app contains an pages array, which defines all the routes for the app. For example, the app definition

app = ace.app("hello1",
              pages = [
                 ace.page("/"),
                 ace.page("/help", "help.go.html")
              ]
             )

defines two routes. / routes to the default index page, /help routes to the help page.

Page #

ace.page is used to define the properties for a single page. The parameters for ace.page are:

PropertyOptionalTypeDefaultNotes
pathFalsestringThe route, should start with a /
fullTruestringindex.go.html if custom layout, else index_gen.go.htmlThe template to use for full page requests
partialTruestringNoneThe template to use for partial page requests
handlerTruefunctionhandler (if defined)The handler function to use for the route
fragmentsTrueace.fragment[][]The fragment array
methodTruestringGETThe HTTP method type: GET,POST,PUT,DELETE etc
typeTruestringhtmlThe response type, html or json

Fragment #

The fragments array in the page definition defines the API interactions within the page. The parameters for ace.Fragment are:

PropertyOptionalTypeDefaultNotes
pathFalsestringThe route, should not start with a /
partialTruestringInherited from pageThe template to use for partial requests
handlerTruefunctionInherited from pageThe handler function to use for the route
methodTruefunctionGETThe HTTP method type: GET,POST,PUT,DELETE etc
typeTruestringhtmlThe response type, html or json
Note: partial and handler are inherited from the page level, unless overridden for the fragment.

For example, in this page definition

ace.page("/game/{game_id}", full="game.go.html", partial="game_info_tmpl", handler=game_handler,
    fragments=[
        ace.fragment(
            "submit", method=ace.POST, handler=lambda req: post_game_update(req, "submit")),
        ace.fragment(
            "refresh", partial="refresh_tmpl")
    ]
)

there are three API’s defined:

  • GET /game/{game_id} : game_handler is the handler function, full page request returns game.go.html, partial HTMX request returns game_info_tmpl template.
  • POST /game/{game_id}/submit : The handler is a lambda function. The game_info_tmpl template partial is inherited from the page as the response for the POST.
  • GET /game/{game_id}/refresh : game_handler is inherited from the page. For full page, it returns the game.go.html response. For partial HTMX requests, refresh_tmpl template is returned.

API Flow #

The API flow is

  • The API is first sent to the matching app
  • Within the app, the API is routed based on the routes defined
  • If there is a handler defined for the matched route, the handler function is called with the request as argument
  • The response template is invoked, with an input map containing a Data property as returned by the handler function
  • If the API type is set to json, the handler response is directly returned, with no template being used
  • If automatic error handling is enabled (error_handler is defined), then the error handler function is called if there is a error during the handler invocation. The error handler does the response processing, the templates defined in the route are not used.

Notes #

  • For HTMX requests, the partial template is used. For regular requests, the page level full template is used
  • If there is a function called handler defined, that is the default handler function for all API’s
  • For non-HTMX update requests (POST/PUT/DELETE), the Post-Redirect-Get pattern is automatically implemented by redirecting to the location pointed to by the Referer header.