Skip to content

handle inside handle_errors does not work if handle_errors <status code> is used #6957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
bludevsk opened this issue Apr 16, 2025 · 3 comments
Labels
bug 🐞 Something isn't working help wanted 🆘 Extra attention is needed

Comments

@bludevsk
Copy link

I tried to create language dependent custom 404 error pages with the following configuration:

handle_errors 404 {
    handle /de/* {
        respond "404 Fehler" 404
    }
    handle /en/* {
        respond "404 Error" 404
    }
    handle {
        respond "404 Fehler" 404
    }
}

But this does not work. It will always evaluate the directives in the first handle block. I also tried named matchers with different matchers (path, path_regexp, file) it always runs the first handle block.

I solved my problem by using the following slightly more complex version which works as excpected:

handle_errors {
    @404 `{err.status_code} == 404`
    handle @404 {
        handle /de/* {
            respond "404 Fehler" 404
        }
        handle /en/* {
            respond "404 Error" 404
        }
        handle {
            respond "404 Fehler" 404
        }
    }
}

The problem was consistent reporducable on
OS: Debian Buster
Caddy version: v2.9.0 h1:rteY8N18LsQn+2KVk6R10Vg/AlNsID1N/Ek9JLjm2yE=
and
OS: Ubuntu 24.04 (WSL)
Caddy version: v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=

@francislavoie
Copy link
Member

If you adapt to JSON with caddy adapt --pretty, what do you get in either case? Compare that. My hunch is it's an issue with the group on the route (which is what makes routes mutually exclusive).

@bludevsk
Copy link
Author

If I use adapt to create the JSON the problem is obvious. You can see that the matcher of the inner handle is ignored an it is always the 404 matcher.

Caddyfile:

test.localhost {
	root * /var/www/
	file_server

	handle_errors 404 {
		@de path_regexp ^/de/.*
		handle @de {
			respond "DE" 404
		}
		@en path_regexp ^/en/.*
		handle @en {
			respond "EN" 404
		}
		handle {
			respond "Default" 404
		}
	}
}

caddy adapt --config Caddyfile --pretty

{
	"apps": {
		"http": {
			"servers": {
				"srv0": {
					"listen": [
						":443"
					],
					"routes": [
						{
							"match": [
								{
									"host": [
										"test.localhost"
									]
								}
							],
							"handle": [
								{
									"handler": "subroute",
									"routes": [
										{
											"handle": [
												{
													"handler": "vars",
													"root": "/var/www/"
												},
												{
													"handler": "file_server",
													"hide": [
														"./Caddyfile"
													]
												}
											]
										}
									]
								}
							],
							"terminal": true
						}
					],
					"errors": {
						"routes": [
							{
								"match": [
									{
										"host": [
											"test.localhost"
										]
									}
								],
								"handle": [
									{
										"handler": "subroute",
										"routes": [
											{
												"group": "group3",
												"handle": [
													{
														"handler": "subroute",
														"routes": [
															{
																"handle": [
																	{
																		"body": "DE",
																		"handler": "static_response",
																		"status_code": 404
																	}
																]
															}
														]
													}
												],
												"match": [
													{
														"expression": "{http.error.status_code} in [404]"
													}
												]
											},
											{
												"group": "group3",
												"handle": [
													{
														"handler": "subroute",
														"routes": [
															{
																"handle": [
																	{
																		"body": "EN",
																		"handler": "static_response",
																		"status_code": 404
																	}
																]
															}
														]
													}
												],
												"match": [
													{
														"expression": "{http.error.status_code} in [404]"
													}
												]
											},
											{
												"group": "group3",
												"handle": [
													{
														"handler": "subroute",
														"routes": [
															{
																"handle": [
																	{
																		"body": "Default",
																		"handler": "static_response",
																		"status_code": 404
																	}
																]
															}
														]
													}
												],
												"match": [
													{
														"expression": "{http.error.status_code} in [404]"
													}
												]
											}
										]
									}
								],
								"terminal": true
							}
						]
					}
				}
			}
		}
	}
}

@francislavoie
Copy link
Member

Huh, yeah that shouldn't happen. It should make sure that all routes are within a subroute, so that they run at the correct layer. PRs welcome if you want to take a shot (I'm a bit busy right now)

@mholt mholt added bug 🐞 Something isn't working help wanted 🆘 Extra attention is needed labels Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐞 Something isn't working help wanted 🆘 Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants