Additional Routers

§Additional Routers

Since Lagom 1.5.0, it is possible to extend a Lagom Service with additional Play Routers.

This is particularly useful when integrating Lagom with existing Play Routers, for instance a Play gRPC Router , or any other Play router that you have at your disposal.

You add an additional router when wiring your Lagom Server. After wiring the Lagom Server, you append the additional Play routers to it.

override lazy val lagomServer =
  serverFor[HelloService](wire[HelloServiceImpl])
    .additionalRouter(wire[SomePlayRouter])

§File Upload Example

The following example shows how you can add a file upload endpoint to an existing Lagom Service.

The example is based on ScalaSirdRouter that allows you to build a Play Router programmatically. It adds an extra path (/api/files) that receives POST calls for multipart-form data.

import play.api.mvc.DefaultActionBuilder
import play.api.mvc.PlayBodyParsers
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._

class FileUploadRouter(action: DefaultActionBuilder, parser: PlayBodyParsers) {
  val router = Router.from {
    case POST(p"/api/files") =>
      action(parser.multipartFormData) { request =>
        val filePaths = request.body.files.map(_.ref.getAbsolutePath)
        Results.Ok(filePaths.mkString("Uploaded[", ", ", "]"))
      }
  }
}

In your application loader, you can wire the router and append it to your Lagom server.

override lazy val lagomServer =
  serverFor[HelloService](wire[HelloServiceImpl])
    .additionalRouter(wire[FileUploadRouter].router)

The path /api/files will now be available on your Lagom service:

curl -X POST -F "data=@somefile.txt" -v  http://localhost:65499/api/files

Note that in that example we are not using the Service Gateway to access the application. We are calling it directly using the service port, in this case, 65499.

§Service Gateway Considerations

An additional router is not part of your application ServiceDescriptor and therefore can’t be automatically published as endpoints to the Service Gateway in development mode.

If you want to access your additional routers through the gateway, you will need to explicitly add the ACL (Access Control List) for it in your ServiceDescriptor definition.

trait HelloService extends Service {

  def hello(id: String): ServiceCall[NotUsed, String]

  final override def descriptor = {
    import Service._
    named("hello")
      .withCalls(
        pathCall("/api/hello/:id", hello _).withAutoAcl(true)
      )
      .withAcls(
        // extra ACL to expose additional router endpoint on ServiceGateway
        ServiceAcl(pathRegex = Some("/api/files"))
      )
  }
}

Once the path is published on the Service Gateway, you can call:

curl -X POST -F "data=@somefile.txt" -v  http://localhost:9000/api/files

Note usage of port 9000 (Lagom’s Dev Mode ServiceGateway)

§Lagom Client Considerations

Additional routers are not part of the Service API and therefore are not accessible from generated Lagom clients. Lagom clients only have access to methods defined on the Service trait.

Additional routers are only part of the exposed HTTP endpoints. To access then, you will need to use an HTTP client, eg: Play-WS

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.