Skip to content
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

fileserver: Support glob expansion in file matcher #4993

Merged
merged 10 commits into from
Sep 5, 2022
Merged

fileserver: Support glob expansion in file matcher #4993

merged 10 commits into from
Sep 5, 2022

Conversation

mholt
Copy link
Member

@mholt mholt commented Aug 30, 2022

This change adds support for glob patterns in the file matcher's try_files parameter (and by extension, the try_files Caddyfile directive).

For a directory like this:

index.1.html   17KB
index.2.html   9KB
index.3.html   23KB

and a config like this:

try_files {http.request.uri.path.file.base}.*.html

a request to /index.html would rewrite to /index.1.html.

Also added the ability to change the policy on the try_files directive:

try_files {http.request.uri.path.file.base}.*.html {
	policy largest_size
}

For the same request, /index.html, this policy would rewrite to /index.3.html.

It'd be nice if we could figure out Caddyfile shorthands for the new {http.request.uri.path.file.base} and {http.request.uri.path.file.ext} placeholders. Maybe they should be like {http.request.uri.path.file_base} instead? We have {path.*} shorthands but that only works one more level deep. We could make it work 2 levels deep or just make different shorthands or use the underscore instead.

I was careful to escape any special glob characters when evaluating placeholders, so a request to /* can't lead to any surprising results. Not a security concern per-se, as the globbing is still within the site root, just unexpected.

Closes #4988. /cc @iamjrock -- can you please try this out?

@mholt mholt added the feature ⚙️ New feature or request label Aug 30, 2022
@mholt mholt added this to the 2.x milestone Aug 30, 2022
case "http.request.uri.path.file.base":
return strings.TrimSuffix(path.Base(req.URL.Path), path.Ext(req.URL.Path)), true
case "http.request.uri.path.file.ext":
return path.Ext(req.URL.Path), true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, with an input of foo.tar.gz, this will return .gz only. Should we write our own logic to repeat .Ext() to pop extensions off the end until none remain, and return that? 🤔

This is relevant when pairing with file.base because the base will probably end up being file.tar which is awkward

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, there are 2 extensions. Imagine a path of index.012abcdf.html -- there's only one file extension and the part in the middle is just a checksum. I'm not sure how to handle that better. It's arbitrary either way, and more commonly there is only 1 ext.

@francislavoie
Copy link
Member

francislavoie commented Aug 30, 2022

Re placeholders, considering we already have {file}, I think we should just add {file.*} as well to cover these two new ones, i.e. {file.base} and {file.ext}.

A realistic example might look like this:

try_files {path} {dir}{file.base}.*{file.ext} =404

i.e. if the file exists as-is on disk, serve that. If the file exists with an infix in front of the extension, rewrite to that instead. If neither, 404.

@iamjrock
Copy link

@mholt @francislavoie Wow guys! I wasn't expecting that, thank you.

Family commitments today but will test it out tomorrow first chance I get.

@mholt
Copy link
Member Author

mholt commented Sep 2, 2022

@iamjrock Did you have a chance to test this out?

@mholt mholt modified the milestones: 2.x, v2.6.0, v2.6.0-beta.1 Sep 2, 2022
@iamjrock
Copy link

iamjrock commented Sep 3, 2022

@iamjrock Did you have a chance to test this out?

Sorry no not yet - hoping to get it tested tonight!

@mholt
Copy link
Member Author

mholt commented Sep 5, 2022

@iamjrock I'll be merging this today in preparation for the first beta release. Hope to hear from you before then if it doesn't work! 😅

@iamjrock
Copy link

iamjrock commented Sep 5, 2022

Hi @mholt I am really sorry, I've had to tool down for a few days due to an unexpected family matter.

But I really appreciate what you've done here and really want to get you that feedback, so I have asked one of my colleagues to test it in my absence and I will follow up.

We're in GMT+8 here so it's early morning and I would expect a reply by close of biz today, possibly earlier.

@mholt
Copy link
Member Author

mholt commented Sep 5, 2022

@iamjrock Ah, no worries -- honestly it's not a big deal, I just wanted to let you know I don't mean to ignore your feedback. I am just going forward with a very unannounced schedule, so I want you to know that I'm not ignoring you or unappreciative of your collaboration with this! 👍

Hope your family is well. Don't go out of your way to test this; it's just going into the first beta, so if something is broken or doesn't meet your requirements we can still fix it later. Cheers!

@mholt mholt merged commit d5ea43f into master Sep 5, 2022
@mholt mholt deleted the fileglob branch September 5, 2022 19:53
francislavoie added a commit that referenced this pull request Sep 5, 2022
This adds:
- `{file.*}` -> `{http.request.uri.path.file.*}`
- `{file_match.*}` -> `{http.matchers.file.*}`

This is a follow-up to #4993 which introduces the new URI file placeholders, and a shortcut for using `file` matcher output.

For example, where the `try_files` directive is a shortcut for this:

```
@try_files file <files...>
rewrite @try_files {http.matchers.file.relative}
```

It could instead be:
```
@try_files file <files...>
rewrite @try_files {file_match.relative}
```
mholt pushed a commit that referenced this pull request Sep 6, 2022
This adds:
- `{file.*}` -> `{http.request.uri.path.file.*}`
- `{file_match.*}` -> `{http.matchers.file.*}`

This is a follow-up to #4993 which introduces the new URI file placeholders, and a shortcut for using `file` matcher output.

For example, where the `try_files` directive is a shortcut for this:

```
@try_files file <files...>
rewrite @try_files {http.matchers.file.relative}
```

It could instead be:
```
@try_files file <files...>
rewrite @try_files {file_match.relative}
```
@iamjrock
Copy link

iamjrock commented Sep 9, 2022

OK thx for the reprieve, all good now thx. My colleagues tested this and report that it is working great for our use case!

@mholt
Copy link
Member Author

mholt commented Sep 9, 2022

Hurray, thanks for confirming!

@mholt mholt modified the milestones: v2.6.0-beta.1, v2.6.0 Sep 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature ⚙️ New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Glob matcher for file names on the *filesystem*
3 participants