Reverse Proxy handle_response with custom error pages and correct status

1. Output of caddy version:


2. How I run Caddy:

Caddy on Windows as a service

a. System environment:

Server 2022 Core

b. Command:

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 Caddy config:

sub.domain.tld {

	root * C:\Caddy\www

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

	log {
		output file C:\Caddy\Logs\sub.domain.tld_access.log {
			roll_size 100mb
			roll_keep 30

	import caddyheaders

	import bad_useragents

	handle_errors {
		rewrite * /static/sub.domain.tld/error.html
		import caddyheaders

	@all_but_static {
		not {
			path /static*
	reverse_proxy @all_but_static http://localhost:8056 {
		@Custom_errors status 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 430 431 451 500 501 502 503 504 505 506 507 508 510 511
		handle_response @Custom_errors {
			rewrite * /static/sub.domain.tld/{rp.status_code}.html
		health_uri /test.jsp
		health_interval 5s
		health_timeout 21s
		health_status 2xx
		health_body "Test successful"


3. The problem I’m having:

We are running an AWS ALB that routes to Caddy which then performs a reverse proxy to Tomcat. I am trying to create replacement error pages that Tomcat sends (we cannot modify tomcat). What I have works with one caveat; a 200 status is always returned and I would like to have the original status returned with the rewrite being used.

I have tried using replace_status and copy_response (inside of handle_response) in many different ways and mostly just get 200 status back or in the case of copy_response it overrides the rewrite. I did find a post using try_files instead of rewrite but this didn’t work either the example (link below) referenced handle_errors.

Ultimately what we are looking to have is the following.

  1. [not working] If custom error pages do not exist a generic message is displayed and correct status is given (gives 404) but for instance it should have sent a 500. This is happening at the handle_response level
  2. [working] If tomcat is not responding at all a generic message is displayed) and correct status is given. This happens at the handle_errors level.
  3. [not working] This is similar to item #1 but in this case the error page exists and is used as well as gives the correct status. This is happening at the handle_response level and the custom page is displayed but a 200 status is sent.

4. Error messages and/or full log output:

Paste logs/commands/output here.

5. What I already tried:

Tons of trying, reading and searching. I must not be using the correct search terms…

6. Links to relevant resources:

When using file_server, you may use its status option to override the status code it should write.

Try this:

file_server {
	status {rp.status_code}

You’ll probably want to move file_server into your handle_response block, not outside of it.

FYI, you can shorten this:

@all_but_static not path /static*

And here, you can probably just use 4xx 5xx instead, I think. No need to list out all the status code numbers.

Just wanted to say I am all set with the suggestions provided. Thanks so much for the assist.

1 Like

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