Add other error pages

This commit is contained in:
Eduard Gert
2026-02-04 17:12:26 +01:00
parent 476785b122
commit b5b7dd4f53
2 changed files with 56 additions and 8 deletions
+44 -8
View File
@@ -1,8 +1,11 @@
package proxy package proxy
import ( import (
"context"
"errors"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"strings"
"sync" "sync"
"github.com/netbirdio/netbird/proxy/internal/roundtrip" "github.com/netbirdio/netbird/proxy/internal/roundtrip"
@@ -31,14 +34,8 @@ func NewReverseProxy(transport http.RoundTripper) *ReverseProxy {
func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
target, serviceId, accountID, exists := p.findTargetForRequest(r) target, serviceId, accountID, exists := p.findTargetForRequest(r)
if !exists { if !exists {
web.ServeHTTP(w, r, map[string]any{ web.ServeErrorPage(w, r, http.StatusNotFound, "Service Not Found",
"page": "error", "The requested service could not be found. Please check the URL, try refreshing, or check if the peer is running. If that doesn't work, see our documentation for help.")
"error": map[string]any{
"code": 404,
"title": "Service Not Found",
"message": "The requested service could not be found. Please check the URL, try refreshing, or check if the peer is running. If that doesn't work, see our documentation for help.",
},
}, http.StatusNotFound)
return return
} }
@@ -60,5 +57,44 @@ func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Set up a reverse proxy using the transport and then use it to serve the request. // Set up a reverse proxy using the transport and then use it to serve the request.
proxy := httputil.NewSingleHostReverseProxy(target) proxy := httputil.NewSingleHostReverseProxy(target)
proxy.Transport = p.transport proxy.Transport = p.transport
proxy.ErrorHandler = proxyErrorHandler
proxy.ServeHTTP(w, r.WithContext(ctx)) proxy.ServeHTTP(w, r.WithContext(ctx))
} }
// proxyErrorHandler handles errors from the reverse proxy and serves
// user-friendly error pages instead of raw error responses.
func proxyErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
title, message, code := classifyProxyError(err)
web.ServeErrorPage(w, r, code, title, message)
}
// classifyProxyError determines the appropriate error title, message, and HTTP
// status code based on the error type.
func classifyProxyError(err error) (title, message string, code int) {
switch {
case errors.Is(err, context.DeadlineExceeded):
return "Request Timeout",
"The request timed out while trying to reach the service. Please refresh the page and try again.",
http.StatusGatewayTimeout
case errors.Is(err, context.Canceled):
return "Request Canceled",
"The request was canceled before it could be completed. Please refresh the page and try again.",
http.StatusBadGateway
case errors.Is(err, roundtrip.ErrNoAccountID):
return "Configuration Error",
"The request could not be processed due to a configuration issue. Please refresh the page and try again.",
http.StatusInternalServerError
case strings.Contains(err.Error(), "connection refused"):
return "Service Unavailable",
"The connection to the service was refused. Please verify that the service is running and try again.",
http.StatusBadGateway
default:
return "Peer Not Connected",
"The connection to the peer could not be established. Please ensure the peer is running and connected to the NetBird network.",
http.StatusBadGateway
}
}
+12
View File
@@ -107,3 +107,15 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, data any, statusCode ...i
} }
w.Write(buf.Bytes()) w.Write(buf.Bytes())
} }
// ServeErrorPage renders a user-friendly error page with the given details.
func ServeErrorPage(w http.ResponseWriter, r *http.Request, code int, title, message string) {
ServeHTTP(w, r, map[string]any{
"page": "error",
"error": map[string]any{
"code": code,
"title": title,
"message": message,
},
}, code)
}