V2 try_file redir question

1. Caddy version (caddy version):

/srv # caddy version
v2.1.1 h1:X9k1+ehZPYYrSqBvf/ocUgdLSRIuiNiMo7CvyGUQKeA=

2. How I run Caddy:

Docker

a. System environment:

Docker on Ubuntu 20.04

b. Command:

n/a

c. Service/unit/compose file:

n/a

d. My complete Caddyfile or JSON config:

johnsiu.com {
	encode gzip
	file_server
	import my_redir_files /blog/{path}
	root * /www/site/johnsiu.com
	@try_files {
		file {
			try_files /blog/{path}index.html /blog/{path}/index.html
		}
	}
	redir @try_files {http.matchers.file.relative}
}

3. The problem I’m having:

The above work according to syntax:

https://johnsiu.com/caddyfile is redirected to https://johnsiu.com/blog/caddyfile/index.html

What I want to do is:

https://johnsiu.com/caddyfile is redirected to https://johnsiu.com/blog/caddyfile/

Moreover, it will redirect even the file exist:

https://johnsiu.com/myip (the filename is myip) actually exist at root. But right now it is redirected to https://johnsiu.com/blog/myip/index.html

4. Error messages and/or full log output:

No error.

5. What I already tried:

I already tried following code:

	@try_files {
		file {
			try_files /blog/{path} /blog/{path}/
		}
	}
	redir @try_files {http.matchers.file.relative}

But no redirect happen and give 404 in browser. It feel like file.try_files cannot match directory.

6. Links to relevant resources:

I think the best thing to do is combine it with a path_regexp matcher that you can craft to match just the part you need, then redirect using the capture groups.

Maybe something like this:

@blog {
	path_regexp blog ^/([^/]+)/?$
	file /blog/{path}index.html /blog/{path}/index.html
}
redir @blog /blog/{re.blog.1}/

Note that the file matcher allows for a shortcut by putting the try_files arguments on the same line if you don’t need to configure any of its other arguments.

Basically the regexp will match a single path segment, with an optional trailing /. I couldn’t figure out on short notice how to use a non-greedy regexp for this, so if you need it to match more than one path segment, you might need to do some figuring out for the ideal regexp for you.

Just tested your code, that works perfectly.

Is there a way to make it only execute if the request path doesn’t exist?

For example, if /caddyfile(file) or /caddyfile/(directory) exist, then the redir code should not execute.

Yep, you can add not file {path} as a third matcher in there, so if the path exists as-is, it won’t match. At least I think that’s what you’re asking for.

Just tried as follow:

@blog {
	path_regexp blog ^/([^/]+)/?$
	file /blog/{path}index.html /blog/{path}/index.html
	not file {path}
}

But /myip is still redirecting. Or did I misunderstand.

So your root is /www/site/johnsiu.com.

Say you get a request with path /foo.

The not file {path} matcher will look for a file /www/site/johnsiu.com/foo. If that exists, then the @blog matcher should not match.

Does that make sense? Maybe I’m misunderstanding your question.

Your understanding is correct.

Both of following exist:
/www/site/johnsiu.com/myip
/www/site/johnsiu.com/blog/myip/index.html

Redirect is happening for https://johnsiu.com/myip even with not file {path}.

Will split the later question into a separate post once I setup a clean testing site.

For the 2nd part: make it only execute if the request path doesn’t exist?

@francislavoie solution works.

I just have to remove /index.html from my original file matcher. So following works:

@blog {
	path_regexp blog ^/([^/]+)/?$
	file /blog/{path} /blog/{path}/
	not file {path} {path}/
}
1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.