-
Notifications
You must be signed in to change notification settings - Fork 411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
some cleanup on recent work serving files and resources #2928
Conversation
0937dd7
to
3473819
Compare
@@ -337,7 +337,11 @@ object Middleware extends HandlerAspects { | |||
} | |||
|
|||
def fromResource(resourcePrefix: String)(implicit trace: Trace): StaticServe[Any, Throwable] = make { (path, _) => | |||
Handler.fromResource(s"${resourcePrefix}/${path.dropLeadingSlash.encode}") | |||
if (resourcePrefix.startsWith(".")) { | |||
Handler.forbidden("Resource prefix cannot start with \".\"") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really happy with this because we are passing off what should be a development-time (i.e., compile-time) error as a client-side HTTP error. Any ideas on how to handle this better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could have either a string interpolator or make fromResource a macro, if we want to check this at compile time.
But I don't think this is necessary. Just use an assert or throw an exception instead of returning the Handler.forbidden
that way, it does not fail on request, but on start-up. Which should be good enough.
Also, I think the prefix should not be allowed to start with ~
or /
. Maybe whitespace as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use Refined to limit the string at compile time, but I agree with @987Nabil that it would be overkill.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think the prefix should not be allowed to start with
~
or/
. Maybe whitespace as well?
Just /
should be forbidden, but something like /public/
should be fine. Does ~
means something in the context of resource paths?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe Handler.die
should exist??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erikvanoosten ~
is the home path in Unix systems. And I would try to avoid some strange side effects. Maybe ~/
is what should be disallowed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erikvanoosten
~
is the home path in Unix systems. And I would try to avoid some strange side effects. Maybe~/
is what should be disallowed
~
might resolve to something in the file system, but it has no meaning in resource paths, see https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html#res_names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
Handler.die
should exist??
That sounds good, but I don't really know how what an implementation would look like. I took a look at ZIO.orDie
to get some ideas, but that method is incredibly complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do, Handler.fromZIO(ZIO.die(...))
. Composition FTW!
Since relative resources are a thing (relative to some class), IMHO we should encourage the users to start the resource prefix with a Then, instead of saying that Now we can express the requirement as a regular expression: // validate that resourcePrefix starts with an optional slash, followed by at least 1 java identifier character
val rp = if (resourcePrefix.startsWith("/")) resourcePrefix else "/" + resourcePrefix
require(rp.length >= 2 && Character.isJavaIdentifierStart(rp.charAt(1)), "resourcePrefix must have at least 1 valid character") This prevents a whole class of confusions about what |
@@ -310,20 +310,19 @@ object Routes extends RoutesCompanionVersionSpecific { | |||
empty @@ Middleware.serveDirectory(path, docRoot) | |||
|
|||
/** | |||
* Creates routes for serving static files from resources at the path `path`. | |||
* Creates routes for serving static files from resources directory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scaladoc makes some assumptions that are not always true. It talks about
'directories' which is not a concept used by the JVM documentation for resources
(I guess the right term would be 'package', but they even avoid that).
Here is a proposal:
Creates a middleware for serving static files at URL path `path` from resources
with the given `resourcePrefix`.
Example:
{{{
Middleware.serveResources(Path.empty / "assets", "/webapp")
}}}
With this middleware in place, a request to `https://www.domain.com/assets/folder/file1.jpg`
would serve the resource `/webapp/folder/file1.jpg`. Note how the URL path is removed and
the resourcePrefix prepended.
Most build systems support resources in the `src/main/resources` directory. In the above
example, the file `src/main/resources/webapp/folder/file1.jpg` would be served.
The `resourcePrefix` defaults to `"/public"`. To prevent insecure sharing of
resource files, `resourcePrefix` must start with a `/` followed by at least 1 [[java.lang.Character.isJavaIdentifierStart valid java identifier character]]. The `/`
will be prepended if it is not present.
With this proposal the default value for resourcePrefix
would change to /pubic
.
I like @jdegoes's suggestion of I'm going to incorporate @erikvanoosten's suggestions. It'll just take a minute while my computer temporarily dies while I run |
1. Change the default path from "." to "public". 2. Add a restriction that the path does not have "." as a prefix. as discussed in a prior PR, here: zio#2887 (comment)
3473819
to
3006ad9
Compare
Hmm, it looks like somebody maybe added Handler.die while I wasn't looking 😄 |
ad1bf19
to
3dddd4b
Compare
- replace `Handler.forbidden` with `require` - firming up logic for resource prefix limitations - some Scaladoc improvements I also fixed a `resourcePrefix` default value from `"."` to `"public"` that I somehow missed before.
3dddd4b
to
73faa16
Compare
as discussed in a prior PR, here:
#2887 (comment)