-
-
Notifications
You must be signed in to change notification settings - Fork 412
chore(#8179) Add json error messages to haproxy #8481
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
Changes from all commits
08dcdc7
3771fcb
a8af842
6e5cbce
e02d290
9326c3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 200 OK | ||
| Content-length: 75 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "200 OK", | ||
| "reason": "Service ready", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| HTTP/1.1 400 Bad request | ||
| Content-length: 107 | ||
| Connection: Close | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "400 Bad request", | ||
| "reason": "Your browser sent an invalid request", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 401 Unauthorized | ||
| Content-length: 129 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "401 Unauthorized", | ||
| "reason": "You need a valid user and password to access this content", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 403 Forbidden | ||
| Content-length: 110 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "403 Forbidden", | ||
| "reason": "Request forbidden by administrative rules", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 404 Not Found | ||
| Content-length: 100 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "404 Not Found", | ||
| "reason": "The resource could not be found", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 405 Method Not Allowed | ||
| Content-length: 164 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "405 Method Not Allowed", | ||
| "reason": "A request was made of a resource using a request method not supported by that resource", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 407 Unauthorized | ||
| Content-length: 129 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "407 Unauthorized", | ||
| "reason": "You need a valid user and password to access this content", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| HTTP/1.1 408 Request Time-out | ||
| Content-length: 127 | ||
| Connection: Close | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "408 Request Time-out", | ||
| "reason": "Your browser didn't send a complete request in time", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 410 Gone | ||
| Content-length: 131 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "410 Gone", | ||
| "reason": "The resource is no longer available and will not be available again", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 413 Payload Too Large | ||
| Content-length: 123 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "413 Payload Too Large", | ||
| "reason": "The request entity exceeds the maximum allowed", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 421 Misdirected Request | ||
| Content-length: 121 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "421 Misdirected Request", | ||
| "reason": "Request sent to a non-authoritative server", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 422 Unprocessable Content | ||
| Content-length: 133 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "422 Unprocessable Content", | ||
| "reason": "The server cannot process the contained instructions", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 425 Too Early | ||
| Content-length: 97 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "425 Too Early", | ||
| "reason": "Your browser sent early data", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 429 Too Many Requests | ||
| Content-length: 134 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "429 Too Many Requests", | ||
| "reason": "You have sent too many requests in a given amount of time", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 500 Internal Server Error | ||
| Content-length: 114 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "500 Internal Server Error", | ||
| "reason": "An internal server error occurred", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 501 Not Implemented | ||
| Content-length: 152 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "501 Not Implemented", | ||
| "reason": "The server does not support the functionality required to fulfill the request", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 502 Bad Gateway | ||
| Content-length: 124 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "502 Bad Gateway", | ||
| "reason": "The server returned an invalid or incomplete response", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 503 Service Unavailable | ||
| Content-length: 124 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "503 Service Unavailable", | ||
| "reason": "No server is available to handle this request", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| HTTP/1.1 504 Gateway Time-out | ||
| Content-length: 109 | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "error": "504 Gateway Time-out", | ||
| "reason": "The server didn't respond in time", | ||
| "server": "haproxy" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # nginx_error_messages | ||
|
|
||
| This directory contains error pages for haproxy. Do not update the error pages | ||
| manually, instead look in `generate.sh` and the `template.json` file | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general I prefer generated code to not be checked in to the repo, and instead generated in CI and published. This means someone doesn't accidentally manually update the output and saves on duplication. What do you think? Is there an advantage to checking in the build output?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see arguments on both sides. The main reason I went with the more explicit pre-generated files is that I expect these will change at most 1-2 times per year and I didn't want to add complexity to the general build process. I imagine debugging an issue with the generated files without having been involved in this PR be more difficult if they're generated on build/start. What if I add a test to ensure the current files are equal to how they will look when running generate.sh? I prefer that over build step as it doesn't complicate the build process and can be run independently from the build. I added a suggestion to what that could look like in this PR in the file |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #!/bin/bash | ||
| ########################################################### | ||
| # | ||
| # Script to generate static error pages for haproxy | ||
| # | ||
| # To update: change messages below or the respective template file | ||
| # and rerun this script | ||
| # | ||
| ########################################################### | ||
| set -eu -o pipefail | ||
| unset IFS | ||
|
|
||
| DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" | ||
|
|
||
| TEMPDIR="$(mktemp -d)" | ||
| trap 'rm -rf "$TEMPDIR"' EXIT | ||
|
|
||
| declare -ar MESSAGES=( | ||
| "200|200 OK|Service ready|" | ||
| "400|400 Bad request|Your browser sent an invalid request|Connection: Close" | ||
| "401|401 Unauthorized|You need a valid user and password to access this content|" | ||
| "403|403 Forbidden|Request forbidden by administrative rules|" | ||
| "404|404 Not Found|The resource could not be found|" | ||
| "405|405 Method Not Allowed|A request was made of a resource using a request method not supported by that resource|" | ||
| "407|407 Unauthorized|You need a valid user and password to access this content|" | ||
| "408|408 Request Time-out|Your browser didn't send a complete request in time|Connection: Close" | ||
| "410|410 Gone|The resource is no longer available and will not be available again|" | ||
| "413|413 Payload Too Large|The request entity exceeds the maximum allowed|" | ||
| "421|421 Misdirected Request|Request sent to a non-authoritative server|" | ||
| "422|422 Unprocessable Content|The server cannot process the contained instructions|" | ||
| "425|425 Too Early|Your browser sent early data|" | ||
| "429|429 Too Many Requests|You have sent too many requests in a given amount of time|" | ||
| "500|500 Internal Server Error|An internal server error occurred|" | ||
| "501|501 Not Implemented|The server does not support the functionality required to fulfill the request|" | ||
| "502|502 Bad Gateway|The server returned an invalid or incomplete response|" | ||
| "503|503 Service Unavailable|No server is available to handle this request|" | ||
| "504|504 Gateway Time-out|The server didn't respond in time|" | ||
| ) | ||
|
|
||
| echo 'http-errors json' | ||
| for message in "${MESSAGES[@]}"; do | ||
| IFS='|' read -r -a message_parts <<<"$message" | ||
| status_code="${message_parts[0]}" | ||
| status_message="${message_parts[1]}" | ||
| status_reason="${message_parts[2]}" | ||
| extra_header="${message_parts[3]:-}" | ||
|
|
||
| error_file="$DIR/${status_code}-json.http" | ||
|
|
||
| LC_ALL="C" # So content-length/$http_body is >1 for multibyte characters | ||
|
|
||
| http_body="$(sed -e "s/__MESSAGE__/$status_message/" -e "s/__REASON__/$status_reason/" <"$DIR/template.json")" | ||
|
|
||
| cat <<EOF >"$error_file" | ||
| HTTP/1.1 $status_message | ||
| Content-length: ${#http_body} | ||
| EOF | ||
|
|
||
| [[ -n "$extra_header" ]] && echo "$extra_header" >>"$error_file" | ||
|
|
||
| cat <<EOF >>"$error_file" | ||
| Cache-Control: no-cache | ||
| Content-Type: application/json | ||
|
|
||
| EOF | ||
|
|
||
| echo -n "$http_body" >>"$error_file" | ||
|
|
||
| echo " errorfile $status_code /usr/local/etc/haproxy/errors/${status_code}-json.http" | ||
|
|
||
| done | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice script! Thanks. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this correctly, this will always respond with JSON regardless of the Accepts header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, since HAProxy is not being called directly by browsers or mobile apps adding a conditional can be considered unnecessary logic (feel free to discuss further in #8179)