Prakash
Prakash

Reputation: 576

Play framework Route case insensitive

We are currently working on Play 2.5.x

We wanted to achive case insensitive routing to be done. Say for example

GET /via/v1/organizations http.organizationApi()

In the URL we wanted to achive

http://localhost:9000/abc/v1/organizations

http://localhost:9000/ABC/V1/OrganIZations

Is the a way to achive this bu using regular expression? Can some one point to or provide me an example?

Upvotes: 3

Views: 1099

Answers (2)

adam wise
adam wise

Reputation: 21

with play 2.8, answer above is not working. the play api has changed so I pasted my code here.

class CaseInsensitive @Inject()(router: Router, errorHandler: HttpErrorHandler, configuration: HttpConfiguration, filters: EssentialFilter*)
extends DefaultHttpRequestHandler(new DefaultWebCommands, None, router, errorHandler, configuration, filters){

override def routeRequest(request: RequestHeader): Option[Handler] = {
  val target = request.target;
  val newPath = target.path.toLowerCase

  val newTarget = request.target.withPath(newPath)
  val newRequest = request.withTarget(newTarget);

  router.handlerFor(newRequest)
}

}

Upvotes: 0

Salem
Salem

Reputation: 12986

You can define a request handler to make the URL case insensitive. In this case, the following handler will just convert the url to lowercase, so in your routes the url should be defined in lowercase:

import javax.inject.Inject

import play.api.http._
import play.api.mvc.RequestHeader
import play.api.routing.Router

class MyReqHandler @Inject() (router: Router, errorHandler: HttpErrorHandler,
                   configuration: HttpConfiguration, filters: HttpFilters
          ) extends DefaultHttpRequestHandler(router, errorHandler, configuration, filters) {

  override def routeRequest(request: RequestHeader) = {
    val newpath = request.path.toLowerCase
    val copyReq = request.copy(path = newpath)
    router.handlerFor(copyReq)
  }
}

And in application.conf reference it using:

# This supposes MyReqHandler.scala is in your project app folder
# If it is in another place reference it using the correct package name
# ex: app/handlers/MyReqHandler.scala --> "handlers.MyReqHandler"
play.http.requestHandler = "MyReqHandler"

Now, if you have a route define to "/persons/create", whatever case combination will work (ex: "/PeRsOns/cREAtE")

There are two caveats though:

  • You can only use this with Scala actions. If your routes file references a Java controller method, you will get an odd exception:

    [error] p.c.s.n.PlayRequestHandler - Exception caught in Netty
    scala.MatchError: Right((play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$14$$anon$3@22d56da6,play.api.DefaultApplication@67d7f798)) (of class scala.util.Right) 
    

    If this is your case you can find more info here

  • If your url have parameters, those will also be transformed. For example, if you have a route like this

    GET /persons/:name/greet       ctrl.Persons.greet(name: String)
    

    a call to "/persons/JohnDoe/greet" will be transformed to "/persons/johndoe/greet", and your greet method will receive "johndoe" instead of "JohnDoe" as parameter. Note that this does not apply to query string parameters. Depending in your use case, this can be problematic.

Upvotes: 3

Related Questions