Combining file_server and reverse_rpoxy

1. My Caddy version (caddy version):

v2.0.0-beta.20 h1:oUNG1uh0UV8LWLlAVDZolFzk112++V/pxY+fF0HLmlY=

2. How I run Caddy:

More of a conceptual thing at this point but I have the need to be able to serve up static content (error pages, graphics etc) while still also performing a proxy on all other requests to a back-end tomcat server.

For example going to https://my.site.com/static/something.jpg would not get proxied but everything else would.

a. System environment:

Windows Server 2012R2

d. My complete Caddyfile or JSON config:

{
   default_sni my.webserver.local
   http_port 80
   https_port 443
   email licensemanager@site.com
}
my.webserver.local {
   tls C:\Caddy\Certificate.pem C:\Caddy\Certificate.key
}
my.site.com {
   @all_but_static {
      not {
         path_regexp ^/static
      }
   }
   @root {
      path_regexp ^/$
   }
   @static {
      path_regexp ^/static
   }
   file_server @static {
      root C:\Caddy\www
   }
   header {
      Strict-Transport-Security "max-age=31536000;"
      Server "C15-83"
      X-XSS-Protection "0"
      X-Server-Test "19"
   }
   handle_errors {
      @502 {
         expression {http.error.status_code} == '502'
      }      
      rewrite @502 https://my.site.com/static/test.html
   }
   redir @root https://my.site.com/epledge{uri}
   tls C:\Caddy\Certificate.pem C:\Caddy\Certificate.key
   reverse_proxy @all_but_static http://localhost:8001
   log {
      output file C:\Caddy\Logs\my_site_com_access.log {
         roll_size 100
         roll_keep 7
      }
   }
}

3. The problem Iā€™m having:

Iā€™m wanting to be able to proxy all request to the back-end tomcat server except for when the url contains /static. Iā€™m trying to use the path_regexp matchers and it seems to work except that the static file contents are not being served up (I do get a response of 200 though).

If i modify the config file as such I am able to access the test.html file. However this wont work the way I need it to because our sites are mixed between being root URLā€™s or having a context defined (/something). Ideally everything but /static would need to be ran through the proxy.

{
   default_sni my.webserver.local
   http_port 80
   https_port 443
   email licensemanager@site.com
}
my.webserver.local {
   tls C:\Caddy\Certificate.pem C:\Caddy\Certificate.key
}
my.site.com {
   @all_but_static {
      not {
         path_regexp ^/static|^/test.html
      }
   }
   @root {
      path_regexp ^/$
   }
   @static {
      path_regexp ^/static
   }
   file_server {
      root C:\Caddy\www
   }
   header {
      Strict-Transport-Security "max-age=31536000;"
      Server "C15-83"
      X-XSS-Protection "0"
      X-Server-Test "20"
   }
   handle_errors {
      @502 {
         expression {http.error.status_code} == '502'
      }      
      rewrite @502 https://my.site.com/static/test.html
   }
   redir @root https://my.site.com/epledge{uri}
   tls C:\Caddy\Certificate.pem C:\Caddy\Certificate.key
   reverse_proxy @all_but_static http://localhost:8001
   log {
      output file C:\Caddy\Logs\my_site_com_access.log {
         roll_size 100
         roll_keep 7
      }
   }
}

4. Error messages and/or full log output:

No errors from access log and running debug in the config and watching the console doesnā€™t show any errors.

5. What I already tried:

Just about everything I can find on google, but Iā€™m still very new to Caddy so I can be easily skipping or not understanding something.

6. Links to relevant resources:

This is a bit opinionated, but I think itā€™s easier to read a Caddyfile when the matchers and the handlers theyā€™re for are grouped together. Also, I made a couple other changes - I copied your header block in handle_errors (you mentioned this was an issue in the other thread where errors would still have the Server: Caddy header), and I set the root for the entire site rather than just on file_server. That last one may or may not fix your issue.

my.site.com {

   root * C:\Caddy\www

   tls C:\Caddy\Certificate.pem C:\Caddy\Certificate.key

   log {
      output file C:\Caddy\Logs\my_site_com_access.log {
         roll_size 100
         roll_keep 7
      }
   }

   header {
      Strict-Transport-Security "max-age=31536000;"
      Server "C15-83"
      X-XSS-Protection "0"
      X-Server-Test "20"
   }

   handle_errors {
      @502 {
         expression {http.error.status_code} == '502'
      }      
      rewrite @502 https://my.site.com/static/test.html
      header {
         Strict-Transport-Security "max-age=31536000;"
         Server "C15-83"
         X-XSS-Protection "0"
         X-Server-Test "20"
      }
   }

   @root {
      path_regexp ^/$
   }
   redir @root https://my.site.com/epledge{uri}
   

   @all_but_static {
      not {
         path_regexp ^/static|^/test.html
      }
   }
   reverse_proxy @all_but_static http://localhost:8001

   file_server
}

Also, thisā€™ll be for you to test, but you can probably just use path /static/* instead of path_regexp for your @all_but_static matcher. Thisā€™ll do a fast prefix match instead of running regexp, more efficient. You can also specify more than one path, and it will check each of them in sequence. So for example path /static/* /test.html

2 Likes

Thanks once again and I learned yet another thing. My config file originally look similar to root * C:\Caddy\www. What I just learned was that in order for /static to be usable in the URL you have to make a C:\Caddy\www\static folderā€¦ duh!

I converted over to using path /static/* in my @all_but_static matcher but if I try to hit something like /thisshouldbeproxied I just get a 404 error via blank page but what should happen is that Tomcat should respond back with a ā€œPage not foundā€ page vs an empty white page.

What do your logs say? Does it reach upstream at all on those requests?

This is what I am getting at the console; is there a native way to record this information into a log file?

2020/03/31 18:22:14.090 ā†[35mDEBUGā†[0m  http.handlers.reverse_proxy     upstream roundtrip      {"request": {"method": "GET", "uri": "/thisdontwork1", "proto": "HTTP/1.1", "remote_addr": "10.2.15.79:32466", "host": "my.site.com", "headers": {"Accept-Encoding": ["br, gzip, deflate"], "X-Forwarded-Port": ["443"], "X-Amzn-Trace-Id": ["Root=1-5e838a56-44dd3938ce6ad54801d83040"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"], "Accept-Language": ["en-US,en;q=0.5"], "Upgrade-Insecure-Requests": ["1"], "Cache-Control": ["max-age=0"], "Cookie": ["AWSALB=cqF3IYs+weyDzzrX0+/Eg5oYi7EIVRW3wGZfn6/LsCl0RV/nFnl2qvfokS/KCuz+ef6pIVQPQVG0b/+dkmBzz7Axu8RY3dar5ZmT+QBRneBht7B5Bfs00RS8pNVs; AWSALBCORS=cqF3IYs+weyDzzrX0+/Eg5oYi7EIVRW3wGZfn6/LsCl0RV/nFnl2qvfokS/KCuz+ef6pIVQPQVG0b/+dkmBzz7Axu8RY3dar5ZmT+QBRneBht7B5Bfs00RS8pNVs"], "X-Forwarded-For": ["71.206.99.203, 10.2.15.79"], "X-Forwarded-Proto": ["https"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0"], "Dnt": ["1"]}, "tls": {"resumed": false, "version": 771, "ciphersuite": 49200, "proto": "", "proto_mutual": true, "server_name": ""}}, "headers": {"Date": ["Tue, 31 Mar 2020 18:22:14 GMT"], "Content-Length": ["0"]}, "duration": 0.0117106, "status": 404}
2020/03/31 18:22:14.094 ā†[31mERRORā†[0m  http.log.access.log0    handled request {"request": {"method": "GET", "uri": "/thisdontwork1", "proto": "HTTP/1.1", "remote_addr": "10.2.15.79:32466", "host": "my.site.com", "headers": {"Dnt": ["1"], "X-Forwarded-For": ["71.206.99.203"], "X-Forwarded-Proto": ["https"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"], "Accept-Language": ["en-US,en;q=0.5"], "Upgrade-Insecure-Requests": ["1"], "Cache-Control": ["max-age=0"], "Accept-Encoding": ["br, gzip, deflate"], "X-Forwarded-Port": ["443"], "X-Amzn-Trace-Id": ["Root=1-5e838a56-44dd3938ce6ad54801d83040"], "Cookie": ["AWSALB=cqF3IYs+weyDzzrX0+/Eg5oYi7EIVRW3wGZfn6/LsCl0RV/nFnl2qvfokS/KCuz+ef6pIVQPQVG0b/+dkmBzz7Axu8RY3dar5ZmT+QBRneBht7B5Bfs00RS8pNVs; AWSALBCORS=cqF3IYs+weyDzzrX0+/Eg5oYi7EIVRW3wGZfn6/LsCl0RV/nFnl2qvfokS/KCuz+ef6pIVQPQVG0b/+dkmBzz7Axu8RY3dar5ZmT+QBRneBht7B5Bfs00RS8pNVs"]}, "tls": {"resumed": false, "version": 771, "ciphersuite": 49200, "proto": "", "proto_mutual": true, "server_name": ""}}, "common_log": "10.2.15.79 - - [31/Mar/2020:13:22:14 -0500] \"GET /thisdontwork1 HTTP/1.1\" 404 0", "latency": 0.015614, "size": 0, "status": 404, "resp_headers": {"Server": ["C15-83"], "X-Xss-Protection": ["0"], "Strict-Transport-Security": ["max-age=31536000;"], "X-Server-Test": ["20"], "Content-Length": ["0"], "Date": ["Tue, 31 Mar 2020 18:22:14 GMT"]}}

If i do the same thing but using the actual tomcat context /pledge/thisdontwork1 I still get a 404 but I will get an actual page served that states the page cannot be found. Are there any other logs I can output to a file (Using MS Windows) that would help us out more? I did place ā€œdebugā€ in the global settings but not really seeing much more.

Well, it looks like it did hit your tomcat backend considering weā€™re seeing http.handlers.reverse_proxy upstream roundtrip.

Any logs in your tomcat backend? I canā€™t really help debugging that part.

Sure is, see the log directive: log (Caddyfile directive) ā€” Caddy Documentation

The requests are actually getting to the tomcat folder and now knowing that Iā€™ve verified that our old setup (using IIS) works exactly the same way. Iā€™ve toyed around with the config and initially was having an issue to where my tests were failing this is what I started with.

   @all_but_context {
      not {
         path /epledge/* /static/*
      }
   }
   redir @all_but_context /epledge{uri}

However when I would go to my.site.com/epledge it would redirect to my.site.com/epledge/epledge. In order to fix it I had to change the config into:

   @all_but_context {
      not {
         path /epledge* /static*
      }
   }
   redir @all_but_context /epledge{uri}

Is this by design / the correct way of doing this?

Yep, because /epledge/* does not match /epledge, as documented here: Request matchers (Caddyfile) ā€” Caddy Documentation

1 Like

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