Reverse Proxy 404 Issue

I have this caddyfile:

http:// {

   proxy /project-one localhost:7000

   proxy /project-two localhost:9000

   root /Users/me/Desktop/www/main-website/
   gzip

   rewrite {
    regexp .*
    to {path} /
  }

}

:7000 {
    root /Users/me/Desktop/www/project-one/
}

:9000 {
    root /Users/me/Desktop/www/project-two/
}

All of the directories are builds of Vue applications. They are all contained in the www parent directory. I am able to access the main website, when I go to /, however when I try to go to /project-one or /project-two, I get a 404 error. How can I fix my reverse proxy issue?

To understand why this is happening, you have to understand a few points:

  • When a web server tries to find a file to serve, it takes the web root and the URI together to determine which file you want.
  • When you specify a path for a proxy, the path you give is simply a prerequisite for Caddy to proxy the entire request to that backend.
  • When Caddy proxies to a backend, it naturally forwards the entire requested URI along with it.

So lets work through what happens when you send a request for /project-one to Caddy on port 80. Caddy:

  • matches the request to a site block (http://)
  • checks the URI (/project-one) and sees that this request qualifies to be proxied
  • makes a new request to localhost:7000/project-one
  • receives its own request on port 7000 and uses the web root + URI to find a file to serve
  • looks in /Users/me/Desktop/www/project-one/project-one and presumably finds nothing
  • responds to itself on port 7000 with a 404, file not found
  • takes that response from itself and returns the 404 over port 80 to your browser

Now, there’s more than one way to fix this, depending on how your backend project is designed to work.

But the most obvious one is to use the without subdirective for proxy.

  • without is a URL prefix to trim before proxying the request upstream. A request to /api/foo without /api, for example, will result in a proxy request to /foo.

https://caddyserver.com/v1/docs/proxy

So using without /project-one would result in Caddy making its upstream connection directly to localhost:7000/ instead of requesting localhost:7000/project-one.

1 Like

I tried using the without subdirective, but it’s still giving me a 404. The directories all have an index.html file associated with it. How can I see the URL that the reverse proxy is making a request to?

You can log it on the upstream server.

Put a log directive in your :7000 site and review the resulting logs to see what requests it’s receiving.

https://caddyserver.com/v1/docs/log

I put in log stdout on my :7000 directive and there was no output in the console, whereas putting log stdout in the http:// had some outputs. What does this mean?

It means that those requests aren’t being proxied.

Is there an index file in your main website?

Your rewrite might be rewriting away from the proxy path, straight to /, stopping anything from actually being proxied.

I was able to get this to work by changing my rewrite rules to

  rewrite {
    if {path} not_match /project-one*
    if {path} not_match /project-two*
    to {path} /
  }

Are there any negative implications to this change that you can see? Or is this the right way to go?

No negative implications. You’re just explicitly ignoring those proxied requests when rewriting, which should be exactly what you need. :+1:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.