Ratpacked: Using Optional Path Tokens
To define endpoints in our Ratpack application we can use optional path tokens. This means that a part of the request can have a value or not, but we can a have single path definition that will match. Normally we define a variable path token with a colon (:
) followed by a variable name. To make this token optional we follow it with a question mark (?
). This tells Ratpack that the token can have a value or not. In our handler we now need to take into account that the path token is optional as well.
Let's write a sample Ratpack application with a path definition containing an optional token. We define a path binding for profiles/:username?
. The path token username
is available in our handler if the value is set, but also a request for profiles
will match for this binding. Then the value for username
is not set.
// File: src/ratpack/Ratpack.groovy
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
// Specify the optional path token username.
// This path definition will match for
// request paths like profiles/mrhaki and
// profiles (without slash and username value).
path('profiles/:username?') {
// Simply render the value of the username
// path token if set, otherwise return "all"
render pathTokens.getOrDefault('username', 'all')
}
}
}
We write the following test to check the different responses we get when we provide values for the optional token or leave out a value:
// File: src/test/groovy/com/mrhaki/ratpack/pathbinding/OptionalPathBindingSpec.groovy
package com.mrhaki.ratpack.pathbinding
import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
class OptionalPathBindingSpec extends Specification {
@AutoCleanup
@Shared
GroovyRatpackMainApplicationUnderTest app =
new GroovyRatpackMainApplicationUnderTest()
@Unroll('path #path should return "#expectedResponse"')
def "check response for request with and without optional token"() {
when:
def response = app.httpClient.get(path)
then:
response.body.text == expectedResponse
where:
path || expectedResponse
'/profiles/mrhaki' || 'mrhaki'
'/profiles/hubert' || 'hubert'
'/profiles' || 'all'
'/profiles/' || ''
'/profiles/mrhaki/42' || 'Client error 404'
}
}
Written with Ratpack 1.1.1.