Fix timeout middleware panic on proxy/WebSocket routes and worker healthcheck
The TimeoutMiddleware wraps the response writer in *http.timeoutWriter which doesn't implement http.Flusher. When the admin reverse proxy or WebSocket upgrader tries to flush, it panics and crashes the container (502 Bad Gateway). Skip timeout for /admin, /_next, and /ws routes. Also fix the Dockerfile HEALTHCHECK to detect the worker process — the worker has no HTTP server so the curl-based check always failed, marking it unhealthy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,6 @@ RUN mkdir -p /app/uploads
|
|||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
||||||
CMD curl -f http://localhost:${PORT:-5000}/api/health/ || exit 1
|
CMD pgrep -x worker > /dev/null && exit 0 || curl -f http://localhost:${PORT:-5000}/api/health/ || exit 1
|
||||||
|
|
||||||
CMD ["/app/start.sh"]
|
CMD ["/app/start.sh"]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
@@ -60,6 +61,16 @@ func SetupRouter(deps *Dependencies) *echo.Echo {
|
|||||||
e.Use(middleware.BodyLimit("1M")) // 1MB default for JSON payloads
|
e.Use(middleware.BodyLimit("1M")) // 1MB default for JSON payloads
|
||||||
e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{
|
e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
|
Skipper: func(c echo.Context) bool {
|
||||||
|
path := c.Request().URL.Path
|
||||||
|
// Skip timeout for reverse proxy and WebSocket routes — the
|
||||||
|
// timeout middleware wraps the response writer in *http.timeoutWriter
|
||||||
|
// which does not implement http.Flusher, causing a panic when
|
||||||
|
// httputil.ReverseProxy or WebSocket upgraders try to flush.
|
||||||
|
return strings.HasPrefix(path, "/admin") ||
|
||||||
|
strings.HasPrefix(path, "/_next") ||
|
||||||
|
strings.HasSuffix(path, "/ws")
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
e.Use(corsMiddleware(cfg))
|
e.Use(corsMiddleware(cfg))
|
||||||
e.Use(i18n.Middleware())
|
e.Use(i18n.Middleware())
|
||||||
|
|||||||
Reference in New Issue
Block a user