Reverse proxy with matcher token

1. Caddy version (caddy version):

V2.3.0

2. How I run Caddy:

caddy is running on Ubuntu 20.0 and was installed from the repo.

a. System environment:

Ubuntu 20.04 w systemD

b. Command:

Caddy runs with systemD and is running in the background.

Paste command here.

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane.

d. My complete Caddyfile or JSON config:

localhost {
    reverse_proxy /api/* 127.0.0.1:3101
    root * /var/www/testwebsite
    file_server
}

3. The problem I’m having:

Hi, I use caddy to run a test server that serves static html. This is working fine. I am trying to use a reverse proxy with a matcher token for any api calls that I am testing. I cannot get this to work. I get a 404 not found whenever I make the calls.

4. Error messages and/or full log output:

curl -v 127.0.0.1:3101/api

  • Trying 127.0.0.1:3101…
  • TCP_NODELAY set
  • Connected to 127.0.0.1 (127.0.0.1) port 3101 (#0)

GET /api HTTP/1.1
Host: 127.0.0.1:3101
User-Agent: curl/7.68.0
Accept: /

  • Mark bundle as not supporting multiuse
    < HTTP/1.1 404 Not Found
    < Content-Type: text/plain; charset=utf-8
    < X-Content-Type-Options: nosniff
    < Date: Mon, 03 May 2021 22:08:38 GMT
    < Content-Length: 19
    <
    404 page not found
  • Connection #0 to host 127.0.0.1 left intact

5. What I already tried:

I read throught the caddyfile-tutorial and it looks like this format should work. I checked directives documentation but didn’t see anything specific to what I was doing.
I also moved the directive around but it didn’t seem to make a difference.

Snip from the docs I read:

In practice, we may want to use the reverse proxy only for API requests, i.e. requests with a base path of /api/. This is easy to do by adding a matcher token:

localhost

file_server
reverse_proxy /api/* 127.0.0.1:9005

6. Links to relevant resources:

Thank you for your time looking into this with me.

A few things:

  • You seem to be making a request to 127.0.0.1:3101/api, but Caddy is listening on port 443 at https://localhost, so you should do curl -v https://localhost/api/

  • The matcher /api/* will match /api/foo but it will not match /api (because you have the / there before the *

  • Moving directives around will have no effect, because they’re sorted according to this directive order

1 Like

ok, I have tried several things with no luck. If I read the directive order it seems to me that it will never be reached as the root directory will always trump it. Maybe a bug?
I have put in a hostname in my host file and then added in app.mydomain.local and it works fine. I also put in a mydomain.local and that works fine. It would be nice to have the directive match and do this without 2 entries in the Caddy file. Any suggestion? Here is the working caddy file as of now:

api.mydomain.local {
    reverse_proxy localhost:3101
}

mydomain.local {
    reverse_proxy /api* localhost:3101 # I left this in the caddy file but it doesn't work.
    root * /var/www/mydomain.local # this works to serve my test website
    file_server
}

Thank your for your time!

The root directive only sets a variable that other directives can later read from, it doesn’t do anything else. The file_server directive is the one that actually serves files (as its name suggests).

You haven’t actually shown me the problem, so I can’t help diagnose. Just saying “it doesn’t work” tells me nothing.

The problem hasn’t changed from above. No matter what configuration I used based on the documentation or your recommendation of removing the trailing / I get a 404 response.

reverse_proxy /api* vs reverse_proxy /api/*

I’m not convinced this is a problem with Caddy. What do you get if you run curl -v https://mydomain.local/api/? It’s more likely this is a problem with your backend server. Check its logs, check Caddy’s logs. Does your backend server’s router handle /api paths?

You need to elaborate here, I can’t guess.

Ok, so I got rid of the host name / local domain and used a registered domain over the Internet and it works fine with this configuration:

xyzplane-test.net {
    root * /var/www/xyzplane-test.net
    file_server
    reverse_proxy /api* 127.0.0.1:3101
}

I have no idea why it doesn’t work with a host file dns name but I guess it doesn’t matter since it will work with a real dns name. What makes less sense is there is nothing in the caddy log or syslog to indicate failure. It’s like it doesn’t route. Might be something on the OS level.

It’s a basic Go backend with standard libray api calls GET and POST. Nothing really crazy.

Thank you.