Jethro
Jethro

Reputation: 3329

Routing by param data type in Play

In Play, what is the best way to handle routing of endpoints based on the data type provided?

GET /my/:id            controllers.MyController.getById(id: Long)
GET /my/:name          controllers.MyController.getByName(name: String)

getById should be called for GET /my/1.
getByName should be called for GET /my/bob (because bob does not cast to Long)

This may not always be the best endpoint design, but if it's required what is the best way to achieve this?

One workaround as noted in this answer is to create single controller methods which try the conversion for you.

GET /my/:arg            controllers.MyController.getByAny(arg: String)

Result getByAny(String arg) {
    try {
        getById( Long.parseLong(arg)) ;
    } catch (Exception e) {
        return getByName(arg)
    }
}

A downside to this is if using Swagger docs you no longer have separate documentation for each route.
You also must do this individually for each conflicting group of routes.

Is there a way to add similar functionality, without breaking documention, to all Endpoints rather than one by one?

Upvotes: 0

Views: 15

Answers (1)

Saskia
Saskia

Reputation: 1056

Try using custom patterns.

GET   /items/$id<[0-9]+>    controllers.Items.getById(id: Long)
GET   /items/$name<[a-zA-Z]+>    controllers.Items.getByName(name)

In fact the second one could probably be simplified to:

GET   /items/:name    controllers.Items.getByName(name)

When multiple routes match the first one to match should be picked.

Upvotes: 1

Related Questions