From 8342304c0e14b1ecd47c7f7beef33a88ebf27db1 Mon Sep 17 00:00:00 2001 From: John Sullivan Date: Wed, 5 Jun 2024 16:03:45 -0500 Subject: [PATCH] Add a resourcePrefix for Middleware.serveResources As it is, `Middleware.serveResources(path)` going to serve any file at all under src/main/resources, including e.g. somebody's reference.conf file. I added a resourcePrefix parameter for this, so that the resources served can be limited to, e.g., src/main/resources/public. I also added delegates for serveResources and serveDirectory in Routes, as per this suggestion: https://github.com/zio/zio-http/pull/2450#issuecomment-1741794986 --- .../src/main/scala/zio/http/Middleware.scala | 14 +++++--- .../src/main/scala/zio/http/Routes.scala | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/zio-http/shared/src/main/scala/zio/http/Middleware.scala b/zio-http/shared/src/main/scala/zio/http/Middleware.scala index 3a359ede6..bc4655086 100644 --- a/zio-http/shared/src/main/scala/zio/http/Middleware.scala +++ b/zio-http/shared/src/main/scala/zio/http/Middleware.scala @@ -334,8 +334,8 @@ object Middleware extends HandlerAspects { } } - def fromResource(implicit trace: Trace): StaticServe[Any, Throwable] = make { (path, _) => - Handler.fromResource(path.dropLeadingSlash.encode) + def fromResource(resourcePrefix: String)(implicit trace: Trace): StaticServe[Any, Throwable] = make { (path, _) => + Handler.fromResource(s"${resourcePrefix}/${path.dropLeadingSlash.encode}") } } @@ -398,9 +398,15 @@ object Middleware extends HandlerAspects { * With this middleware in place, a request to * `https://www.domain.com/assets/folder/file1.jpg` would serve the file * `src/main/resources/folder/file1.jpg`. + * + * Provide a `resourcePrefix` if you want to limit the the resource files + * served. For instance, with `Middleware.serveResources(Path.empty / + * "assets", "public")`, a request to + * `https://www.domain.com/assets/folder/file1.jpg` would serve the file + * `src/main/resources/public/folder/file1.jpg`. */ - def serveResources(path: Path)(implicit trace: Trace): Middleware[Any] = - toMiddleware(path, StaticServe.fromResource) + def serveResources(path: Path, resourcePrefix: String = ".")(implicit trace: Trace): Middleware[Any] = + toMiddleware(path, StaticServe.fromResource(resourcePrefix)) /** * Creates a middleware for managing the flash scope. diff --git a/zio-http/shared/src/main/scala/zio/http/Routes.scala b/zio-http/shared/src/main/scala/zio/http/Routes.scala index 4fbde164d..6788a0c9c 100644 --- a/zio-http/shared/src/main/scala/zio/http/Routes.scala +++ b/zio-http/shared/src/main/scala/zio/http/Routes.scala @@ -16,6 +16,8 @@ package zio.http +import java.io.File + import zio._ import zio.http.Routes.ApplyContextAspect @@ -293,6 +295,37 @@ object Routes extends RoutesCompanionVersionSpecific { def singleton[Env, Err](h: Handler[Env, Err, (Path, Request), Response])(implicit trace: Trace): Routes[Env, Err] = Routes(Route.route(RoutePattern.any)(h)) + /** + * Creates routes for serving static files from the directory `docRoot` at the + * url path `path`. + * + * Example: `Routes.serveDirectory(Path.empty / "assets", new + * File("/some/local/path"))` + * + * With this routes in place, a request to + * `https://www.domain.com/assets/folder/file1.jpg` would serve the local file + * `/some/local/path/folder/file1.jpg`. + */ + def serveDirectory(path: Path, docRoot: File)(implicit trace: Trace): Routes[Any, Nothing] = + empty @@ Middleware.serveDirectory(path, docRoot) + + /** + * Creates routes for serving static files from resources at the path `path`. + * + * Example: `Routes.serveResources(Path.empty / "assets")` + * + * With this routes in place, a request to + * `https://www.domain.com/assets/folder/file1.jpg` would serve the file + * `src/main/resources/folder/file1.jpg`. + * + * Provide a `resourcePrefix` if you want to limit the the resource files + * served. For instance, with `Routes.serveResources(Path.empty / "assets", + * "public")`, a request to `https://www.domain.com/assets/folder/file1.jpg` + * would serve the file `src/main/resources/public/folder/file1.jpg`. + */ + def serveResources(path: Path, resourcePrefix: String = ".")(implicit trace: Trace): Routes[Any, Nothing] = + empty @@ Middleware.serveResources(path, resourcePrefix) + private[http] final case class Tree[-Env](tree: RoutePattern.Tree[RequestHandler[Env, Response]]) { self => final def ++[Env1 <: Env](that: Tree[Env1]): Tree[Env1] = Tree(self.tree ++ that.tree)