Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Play controller for serving a React App out of /public - including front-end routes
package controllers
import play.api.mvc.{Action, Controller}
import play.api.Logger
import javax.inject.Inject
import java.io.File
import play.api.libs.json.Json
class FrontEndServingController @Inject() (val assets:Assets) extends Controller {
val logger = Logger("FrontEndServingController")
val publicDirectory = "/public"
val indexFile = "index.html"
val physicalPublicDirectory="./public/"
lazy val physicalAssets:Set[String] = {
val startingDirectory = new File(physicalPublicDirectory)
deepList(startingDirectory)
}
private def deepList(f: File): Set[String] = {
val these = f.listFiles.toSet
val inHere = these.filter(_.isFile).map { f =>
f.getPath.replace(physicalPublicDirectory, "")
}
val belowHere = these.filter(_.isDirectory).flatMap(deepList)
inHere ++ belowHere
}
val index = serve(indexFile)
def frontEndPath(path: String) = serve(path)
private def serve(path: String) = {
if (physicalAssets.contains(path)) {
logger.debug(s"Serving physical resource: '$path'")
assets.at(publicDirectory, path, true)
} else {
logger.debug(s"Serving virtual resource: '$path'")
// It's some kind of "virtual resource" -
// a front-end "route" most likely
assets.at(publicDirectory, indexFile, true)
}
}
val listPhysicalAssets = Action {
Ok(Json.toJson(physicalAssets))
}
}
Owner

themillhousegroup commented Jul 8, 2017

Example of corresponding routes file:

...
# Last of all, fall through to the React app
GET         /list-assets               controllers.FrontEndServingController.listPhysicalAssets
GET         /                          controllers.FrontEndServingController.index
GET         /*file                     controllers.FrontEndServingController.frontEndPath(file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment