V2: Having trouble with rewrite

1. My Caddy version (caddy -version):

v2.0.0-beta9 (from github)

2. How I run Caddy:

caddy adapt --config caddyfile

a. System environment:

running on opensuse tumbleweed

b. Command:

paste command here

c. Service/unit/compose file:

paste full file contents here

d. My complete Caddyfile:

domain.com, www.domain.com

templates
encode gzip
file_server
root * /home/html
php_fastcgi unix//tmp/php.sock

rewrite / {
regexp ^/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$
to /index.php?vid={1}&mid={2}&document_srl={3}
}

3. The problem I’m having:

I cannot adapt caddyfile.

4. Error messages and/or full log output:

adapt: parsing caddyfile tokens for ‘rewrite’: Caddyfile:9 - Error during parsing: Wrong argument count or unexpected line ending after ‘rewrite’

5. What I already tried:

FYI, original apache rewrite was:
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?vid=$1&mid=$2&document_srl=$3 [L,QSA]

converted for nginx from apache rewrite was:
rewrite ^/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$ /index.php?vid=$1&mid=$2&document_srl=$3 last;

and I read about some forum articles but I cannot understand why I’m failing to adapt my config.

I tried to rewrite it by using matcher, but there’s no luck too.

6. Links to relevant resources:

Hi @nginx_x, welcome to the Caddy community.

Using a matcher should be the way to go here. The rewrite you’re using is v1-specific configuration and won’t work in v2. Can you post the config you tried with the matcher?

Thanks for your reply.

I tried a matcher method like this:

matcher a {
path_regexp ^/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$
}
rewrite a to /index.php?vid={1}&mid={2}&document_srl={3}

“to” isn’t a literal “to”, you want to replace it with the destination.

rewrite a /index.php?vid={1}&mid={2}&document_srl={3}

So I tested this configuration :

but caddy returned an error:

Can you tell me where I made a mistake?

I’m actually seeing two problems here. First is the arg count issue, which I’m not sure about. That should be the correct method to use rewrite. It may be a different error provoking this error message.

I hit up @francislavoie for second set of eyes on this and he pointed out a second issue, which is that to address the capture groups, you actually need different placeholders in v2:

If you are using regexp matchers, capture groups (both named and numeric) are available as well:

{http.matchers.PATH_REGEXP.PATTERN_NAME.CAPTURE_GROUP_NAME}

Replacing:

  • PATH_REGEXP with the name of the matcher that has the regular expression.
  • PATTERN_NAME with the lower-cased name you gave the pattern.
  • CAPTURE_GROUP_NAME with the name or index number of the capture group in the regular expression.

https://github.com/caddyserver/caddy/wiki/v2:-Documentation#http-placeholders

So {1} in the rewrite target should be {http.matchers.a.???.1}, where ??? should be a name you’ve given for the regex - but the documentation doesn’t specify a method to name a regex in a matcher. The regex name is able to be provided in JSON configuration, so you might need to change away from the Caddyfile to JSON to get it working until we sort that question out.

Perhaps @matt can provide some insight into this - both the error and the regex name?

1 Like

Okay, here’s nothing I can do, for now :sob: because I don’t familiar with JSON things. That makes me painful!

Thanks a lot, and I will wait.

1 Like

I ninja edited it in after the initial post, but if you’d like, you could try learning the JSON configuration and setting it up that way. You can adapt the Caddyfile without the rewrite in it to start with, then add the rewrite configuration in JSON, which should be fully functional. Otherwise, yeah, hang ten, we’ll look into it.

Okay, I will figure it out, with JSON way, according to v2 Documentation posted on Github.

but I’m not sure about it :0 because it looks very hard. thanks anyway!

Bit of advice - Google one of those online JSON editors, they’ll keep your structure nice and neat and present it to you in a way that’s easy to read.

1 Like

Oh, sorry everyone. Lemme try to help.

Fair warning: it’s well after midnight and I should be asleep. I haven’t tested this config but I have verified that it loads successfully.

This is probably what you want:

localhost

templates
encode gzip
file_server
root * /home/html
php_fastcgi unix//tmp/php.sock

matcher foo {
	path_regexp myregex ^/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$
}
rewrite match:foo /index.php?vid={http.matchers.path_regexp.myregex.1}&mid={http.matchers.path_regexp.myregex.2}&document_srl={http.matchers.path_regexp.myregex.3}

Yes, it’s undocumented that regexes can have names specified before them. My bad. Will fix that now.

Also, yes, I agree these placeholders are WAY too long, I will have to see how we can trim them down. The Caddyfile gives us the option to make “shorthand” placeholders. It already has several: https://github.com/caddyserver/caddy/wiki/v2:-Documentation#shorthand-placeholders - we might be able to make some that work for these cases (like {myregex.2} and just assume that it’s a path regex? I dunno).

Sorry it wasn’t clear. Keep the conversation going so I can work on improving it this week.

(Thank you for using v2 while it is still in beta!!)

1 Like

So I’ve found my typo, which caused parsing error. I tried to call a matcher by just name, but I need to call it by match:name! That was a simple misunderstanding of documentation. :wink:

And your example helped me a lot. Finally, I’ve just got to activate my little website, after rewriting 17 rules. This is one-time work so I don’t have anything to complain.

But, it would be lovely if I call rewrite target as {1} {2} just like old days.

(And I found that I cannot use matcher {} in one line, so I seperated into 3 lines like you did.)

1 Like

Glad to hear it is working for you!

I’m wanting to improve this, both the documentation and the implementation. What would make matchers easier?

I would love this too, but the problem is, how does it know which regex the capture numbers are referring to? Matchers in Caddy 2 can have more than one regex…

Ah yes, we like to keep things consistent and clean. :slight_smile:

After many thoughts, I think current system is sufficiently effective, at least for me.

I considered some ideas:

  1. call matcher by matcher:name, not match:name, for intuitive use
  • it is not a crucial factor, and I don’t think it will be effective that much.
  1. maybe caddy v2 could implement two method at the same time, like using matcher(current) and just one regexp-specific rewrite(maybe, rrewrite).
  • but would it be worth it? Idk
  1. Maybe the confusion is coming from matcher’s versatility and flexibility, or lack of basic example conf which I’ve mentioned in Github Issue #2858
  • Some of real world examples will be a great addition to documentation, sometimes I feel the docs are presenting syntax only.
  • But I don’t have any more specific thoughts, maybe due to lack of caddy experience(I used caddy just for 2 week!). I need to dig into caddy a lot more if I want to propose an alternative implementation.
1 Like

Thank you for your thoughtful consideration of this, @nginx_x – really appreciate it.

I can understand the disparity between the matcher directive and using the matchers with match: instead of matcher:. I will think about it too… but yeah, not sure if it will be that effective.

Like you, I am not sure this would be worth it…

Yes, I agree! The best documentation has 4 parts:

  • Tutorials
  • How-to
  • Explanation
  • Reference

We only have an ad-hoc reference for Caddy 2, we haven’t written its documentation yet. :slight_smile: Will definitely get to that soon, it’s a requirement before we launch it.