Cannot migrate rewrite rule from v1 to v2

1. Caddy version (caddy version):

v2.0.0 h1:pQSaIJGFluFvu8KDGDODV8u4/QRED/OPyIR+MWYYse8=

2. How I run Caddy:

systemctl start caddy.service

a. System environment:

Linux debian 4.9.0-8-amd64 #1 SMP Debian 4.9.110-3+deb9u5 (2018-09-30) x86_64 GNU/Linux

b. Command:

systemctl start caddy.service

c. Service/unit/compose file:

the one provided by the package manager

3. The problem I’m having:

Hi,
I had the following rewrite rule in caddy v1:

    rewrite {
        regexp ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
        to {path} {path}/ /{1}index.php?{2}&{query}
    }

For reference, this would be the rule for nginx:

location / {
    index index.php;
    
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/(forum/|cms/|wcf/|calendar/|filebase/|blog/|gallery/)?([^.]+)$ /$1index.php?$2 last;
}

4. Error messages and/or full log output:

none

5. What I already tried:

My current config looks like this, but nothing is working so far…

        file_server

        # Add trailing slash for directory requests
        @canonicalPath {
                file {
                        try_files {path}/index.php
                }
                not path */
        }
        redir @canonicalPath {path}/ 308

        # If the requested file does not exist, try index files
        @indexFiles {
                file {
                        file_regexp dirs ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
                        try_files {path} {path}/ /{http.regexp.dirs.1}index.php?{http.regexp.dirs.2}&{query}
                        split_path .php
                }
        }
        rewrite @indexFiles {http.matchers.file.relative}

        # Proxy PHP files to the FastCGI responder
        @phpFiles {
                path *.php
        }
        reverse_proxy @phpFiles unix//var/run/php-fpm.sock {
                transport fastcgi {
                        split .php
                }
        }

That’s not a valid matcher, you want path_regexp. See the file matcher syntax here, path_regexp is not an option of file, but instead its own matcher.

One of the problems are that the order in which matchers are executed is not guaranteed, so trying to use the regexp result in the same named matcher can’t be relied upon.

Here’s a related thread for I think the same app as you’re using, but unfortunately that user never got to a working solution.

My best suggestion would be something like this (also you don’t need to copy and modify the php_fastcgi expanded form, the rewrite below will happen beforehand and it should be fine to use php_fastcgi as-is):

@dirs {
	path_regexp dirs ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
}
handle @dirs {
	try_files {path} {path}/ /{http.regexp.dirs.1}index.php?{http.regexp.dirs.2}&{query}
}

This will make sure that the path_regexp matcher happens first, then in a subroute, will invoke the try_files directive (different than the try_files matcher, it’s essentially a shortcut, see the docs) to rewrite the path.

1 Like

Thank you, but the “rule” for forum/ is not working fine, I will explain whats different with that path below.

I have now this one kind of working:

        file_server

        @a {
                path_regexp a ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
        }

        rewrite @a /{http.regexp.a.1}index.php?{http.regexp.a.2}&{query}

The only thing left is, that /forum or /forum/ is not working, but everything below does, like /forum/foo.
The special thing on /forum is, that it is a real folder with an index.php inside. So somethign is not working there.
(I’m using the short php_fastcgi syntax again)

That’s the same thing the other user encountered in the other thread :cry:

I guess you could add a separate rule like this?

@forum {
	path /forum /forum/
}
rewrite @forum /forum/index.php

(Also once you have it working, please post your full Caddyfile so that the next person to run into this has something concrete to reference :slightly_smiling_face:)

1 Like

Yeah, just noticed he had the same issue as I did…
The separate rule is working fine and now it looks like everything is running as it should.
Thank you very much!
As requested my Caddyfile:

host.tld {
        root * /var/www/host.tld/www/
        log /var/log/caddy/host.tld-access.log

        php_fastcgi unix//var/run/php-fpm.sock

        file_server

        @wcf {
                path_regexp wcf ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
        }
        rewrite @wcf /{http.regexp.wcf.1}index.php?{http.regexp.wcf.2}&{query}

        @forum {
                path /forum /forum/
        }
        rewrite @forum /forum/index.php
}
2 Likes

That’s great! I replied in the other thread, so hopefully they can take from your example :smile:

Btw, a couple comments. In Caddy v2.1 (beta 1 is already out if you want to try it), we have multiple syntax improvements that can simplify your config.

Also, you’re using the log directive incorrectly; in Caddy v2.0, it would silently ignore the arguments on the same line, the syntax for log is different in v2 than v1. In v2.1, we throw a parse error with the syntax you used.

Here’s how it would look in v2.1:

host.tld {
	root * /var/www/host.tld/www/
	log {
		output file /var/log/caddy/host.tld-access.log
	}

	php_fastcgi unix//var/run/php-fpm.sock

	file_server

	@wcf path_regexp wcf ^/(forum/|cms/|calendar/|filebase/|blog/|gallery/)?([a-zA-Z0-9-/]+)$
	rewrite @wcf /{re.wcf.1}index.php?{re.wcf.2}&{query}

	@forum path /forum /forum/
	rewrite @forum /forum/index.php
}

See the examples and syntax for log here:

2 Likes

Thanks for pinging me there! Due to situations, I was without internet for a few weeks, only got internet back since yesterday.

I’ve tried the rewrite syntax above, it works like a charm! Thanks so much!

1 Like

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