§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 "[email protected]" -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 "[email protected]" -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