Errors and Rewrites

I was trying to implement fairly wildcard error documents, but simply using

errors {
  404 error.php
}

did nothing, quite apart from how the docs describe it. However, if I add in a rewrite like this

rewrite {
  to {path} {path}/ /error.php
}

it will. But the status code will be 200, whereas I expected it to be 404 (index2.php did not exist).

Which is the correct directive or combination of directives to properly handle 4xx and 5xx errors by returning an error page with the correct status?

My caddyfile (with Caddy v0.9.3) looks like this:

test.dev:81 {
	root C:\caddy\test
	log logs/access.log
	errors logs/error.log
	ext .html .htm .php
	gzip
	tls off
	status 403 {
		/lib
		/mails
	}
	errors {
		404 error.php
	}
	rewrite {
		to {path} {path}/ /error.php
	}
	startup C:/MariaDB/bin/mysqld.exe --datadir=C:/MariaDB/data &
	startup C:/Caddy/php-5.6.23/php-cgi.exe -b 127.0.0.1:9001 &
	fastcgi / 127.0.0.1:9001 php {
		index index.php
	}
	shutdown C:/MariaDB/bin/mysqladmin.exe -u root shutdown
}

Any effects from adding /errors.php under status block ?

Adding status 404 /error.php seemingly works in conjunction with the initial setup, but error.php returns without parsing. However, merging the errors logs/error.log with error pages into:

errors {
  log error.log
  * /error.php
}

Does work, thus the specific 404 error and rewrite is not needed. Though error.php is still not parsed and returns as pure text, could this be due to the fastcgi-directive?

Out of curiosity, what happens if you generate a .html file for your error page and use that instead of a .php file? I can’t see anything wrong with your fastcgi usage, except perhaps that index index.php is redundant (you’re using the php preset, which does that already - see the fastcgi docs).

Using a simple html-file, ohno.html with content <h1>Oh no, Error!</h1>, works as expected.

The benefit of the wildcard error is that error.php can handle all special error directions, such as displaying a search box in the case of a 404, whilst pure html would require a multitude of files generated to fit the site in question.

Have you found a solution for your problem? I am also trying to get php error files to work.

Had another quick look into this.

It looks like the error handler is written specifically to serve a static page, including setting a text/html Content-Type header. It simply copies the contents of the nominated file into the response body.

Seems pretty damning for you guys wanting to have processed PHP error pages. Templates wouldn’t work for you either, so I think your only solution for a comprehensive set of custom error pages is to start generating all those files.

Unfortunately this is not an Option as I don’t control which URLs would be served. My use case is a redirector page for everything from an old Domain example.com to an new domain example.net including subdomains.
I chose caddy because of the auto ssl feature for subdomains which gives me effective wildcard support with letsencrypt.
But because I don’t have any legitimate content on that page I will look into a redirect rule which just passes the Path and arguments to index.php.
I will report back if that worked.

Hi,

that worked for me. I need jquery for the redirect page to also get the fragment correct in the redirect. So my redirect looks like this:

rewrite / {
  regexp .*
  if {file} not jquery-redirector.js
  to /index.php{uri}
}

This is unfortunate, even if static error pages is still a norm - outdated though it may be. A benefit of relying on a programming-language surely is that things can be handled dynamically, so I hope there’s a rewrite for it in near future.

If you have a dynamic backend, why isn’t it simply handling dynamic errors? Caddy’s a web server and can proxy PHP to a backend, but why would the backend not be able to handle errors, if it’s the one processing PHP and you want PHP error pages?

I’m not quite sure to be honest, even with a defined error-directive like this:

errors {
  log error.log
  * /ohno.html
}

An incorrect address ends at Caddy saying “No input file specified.”, rather than <h1>Oh no, Error!</h1> from ohno.html. This is also the case with:

errors {
	404 ohno.html # Not Found
	500 ohno.html # Internal Server Error
}

There’s always the chance that I am just confusing the setup of directives, so for reference here’s the full definition from the Caddyfile (as it stands at present):

test.dev:81 {
	root C:\caddy\test
	log test/logs/access.log
	ext .html .htm .php
	gzip
	tls off
	status 403 {
		/lib
		/mails
	}
	errors {
		404 ohno.html # Not Found
		500 ohno.html # Internal Server Error
	}
	rewrite / /portal.php
	startup C:/MariaDB/bin/mysqld.exe --datadir=C:/MariaDB/data &
	startup C:/Caddy/php-5.6.23/php-cgi.exe -b 127.0.0.1:9001 &
	fastcgi / 127.0.0.1:9001 php {
		index index.php
	}
	shutdown C:/MariaDB/bin/mysqladmin.exe -u root shutdown
}

This is using Caddy v0.9.3, and as far as I can tell the subsequent two patches do not address this in particular.

What response code does Caddy return when you get this page? Something tells me Caddy is receiving this response from php-cgi and relaying it to the client, possibly even with a 200 OK.

    fastcgi / 127.0.0.1:9001 php {
		index index.php
	}

The index subdirective is redundant per the php preset docs, you can replace with fastcgi / 127.0.0.1:9001 php.

I replaced the redundant directive with this:

startup C:/MariaDB/bin/mysqld.exe --datadir=C:/MariaDB/data &
startup C:/Caddy/php-5.6.23/php-cgi.exe -b 127.0.0.1:9001 &
fastcgi / 127.0.0.1:9001 php

When I access an existing file, like portal.php, the page returns a 200, but a non-existing file, like portal2.php returns a 404 (per Chrome’s DevTools). This is confirmed by the access.log:

::1 - [25/Jan/2017:20:32:56 +0100] "GET /portal.php HTTP/1.1" 200 5098
::1 - [25/Jan/2017:20:33:00 +0100] "GET /portal2.php HTTP/1.1" 404 49

To confirm, you’re getting 404’s properly, but it’s not giving you ohno.html as expected, you’re still getting “No input file specified”?

Hmm. Do you get the same issue without rewrite / /portal.php in the Caddyfile?

Yes, that is correct. Where I would expect “Oh no, Error!”, I get “No input file specified”. There are some interesting results from removing rewrite / /portal.php:

Accessing test.dev:81/ returns "Oh no, Error!"
Accessing test.dev:81/portal.php returns the portal page
Accessing test.dev:81/portal2.php returns "No input file specified."
Accessing test.dev:81/portal2 returns 'Oh no, Error!'

Add rewrite / /portal.php back in, and the following results:

Accessing test.dev:81/ returns the portal page
Accessing test.dev:81/portal.php returns the portal page
Accessing test.dev:81/portal2.php returns "No input file specified."
Accessing test.dev:81/portal2 returns 'Oh no, Error!'

I had not noticed the difference before, nor really tested it. If I remove ext .html .htm .php (but keep the rewrite / /portal.php) from the Caddyfile, I get the same result where non-existent paths with file-endings ending in .php (but not .html for example) end in the “No input file specified.”

Might it be that in addition to the ext-directive, I need to rewrite /FILE.php to /FILE?

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