Skip to content

The Pattern Language

Sam Hindmarsh edited this page Mar 27, 2019 · 4 revisions

Simple matching

When defining a pattern, you may want to match certain groups of the path and extract the information found within to use for routing the user to specific places. As an example, let's take the URL https://plunge.example.com/submarines/12345/buy from the README. Here, all our the app cares about is that the link represents the submarine purchase flow, and the ID of the vessel we want to buy. We know from our pattern matching that this link represents the purchase flow, so all we need to capture is the part of the path which represents the ID (in this case, 12345). We might define our pattern as such:

pattern("/submarines/{id}/buy") { /* Launch purchase flow */ }

Here we're matching on a group using the curly brace syntax {..}. This will extract the ID path segment and label it as id. We can now use this extracted group in our handler:

pattern("/submarines/{id}/buy") { 
  result -> router.launchPurchaseFlow(id = result.params["id"])
}

Easy!

Matching with flags

This pattern may be catching too much, however. Imagine we had a page on our site for getting help with purchasing a submarine: https://plunge.example.com/submarines/help/buy. We know an ID should only ever be numeric, but our pattern still catches this path (see the Testing guide for how you can set up a test to ensure this link is not caught).

To prevent this issue, we can add flags to our pattern to specify which type of characters we should match on. Our above example now becomes this:

pattern("/submarines/{d|id}/buy") { result -> router.launchPurchaseFlow(id = result.params["id"]) }

Here, we define our flags before the name of the group to capture. We use the d flag to specify that this path should only match when the specified group exclusively contains digits. Now we no longer have to worry about catching unsupported links!

See the Flags page for a comprehensive, up-to-date list of supported flags.

Query string matching

By default, query strings are passed to the handler function via the params map. However, there may be cases where we require certain query string parameters to be present. An example may be a URL where critical information is conveyed in the query string, such as https://plunge.example.com/login?token=a1b2c3. Here, the token is a required field (it's necessary to log the user in). We can define our pattern as such:

pattern("/login", requiredQueryParams = listOf("token")) { 
  result -> router.logInMember(token = result.params["token"]) 
}

In this case, the accepted handler will only be invoked if the token query string parameter is found.

Clone this wiki locally