{"record":{"id":"5d53d326f05e5964","repo":"gofr-dev/gofr","slug":"response-writer-does-not-support-hijacking","errorCode":null,"errorMessage":"response writer does not support hijacking","messagePattern":"response writer does not support hijacking","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/http/middleware/logger.go","lineNumber":19,"sourceCode":"package middleware\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"go.opentelemetry.io/otel/trace\"\n)\n\nvar errHijackNotSupported = errors.New(\"response writer does not support hijacking\")\n\n// JSON envelope keys for the panic-recovery error response written by\n// panicRecovery. Defined as constants so the same spellings stay\n// consistent across the package and the goconst linter is satisfied.\nconst (\n\tenvelopeCodeKey    = \"code\"\n\tenvelopeStatusKey  = \"status\"\n\tenvelopeMessageKey = \"message\"\n)\n\n// StatusResponseWriter Defines own Response Writer to be used for logging of status - as http.ResponseWriter does not let us read status.\ntype StatusResponseWriter struct {\n\thttp.ResponseWriter\n\tstatus int\n\t// wroteHeader keeps a flag to keep a check that the framework do not attempt to write the header again. This was previously causing\n\t// `superfluous response.WriteHeader call`. This is particularly helpful in scenarios where the developer has already written header\n\t// in any custom middlewares.\n\twroteHeader bool","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/http/middleware/logger.go#L1-L37","documentation":"errHijackNotSupported is a sentinel in GoFr's logging middleware returned by StatusResponseWriter.Hijack when the wrapped http.ResponseWriter does not implement http.Hijacker. Connection hijacking (needed for WebSockets and upgraded protocols) is only possible if the underlying writer supports it, so this error surfaces that limitation. It's normally wrapped by the 'cannot hijack connection' error.","triggerScenarios":"Calling Hijack() on a StatusResponseWriter whose underlying ResponseWriter lacks a Hijack() method, e.g. when a WebSocket upgrade handler runs through a writer chain (logging, gzip, test fakes) that doesn't implement http.Hijacker.","commonSituations":"Adding logging or compression middleware above a WebSocket endpoint, using httptest.ResponseRecorder in tests, or custom reverse-proxy writers that don't forward the Hijacker interface.","solutions":["Ensure the underlying ResponseWriter implements http.Hijacker (forward Hijack in custom wrappers)","Register WebSocket endpoints so they aren't wrapped by non-hijackable middleware writers","In tests use a real httptest server or a hijacker-capable fake instead of ResponseRecorder","Check for errors.Is(err, middleware.ErrHijackNotSupported) and fall back to a plain connection path"],"exampleFix":"// before\ntype gzipResponseWriter struct{ http.ResponseWriter } // no Hijack -> errHijackNotSupported\n// after\ntype gzipResponseWriter struct{ http.ResponseWriter }\nfunc (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {\n    if h, ok := w.ResponseWriter.(http.Hijacker); ok { return h.Hijack() }\n    return nil, nil, http.ErrNotSupported\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := underlying.(http.Hijacker); !ok {\n    return errors.New(\"underlying response writer does not support hijacking; websocket upgrade will fail\")\n}","typeGuard":"func supportsHijack(w http.ResponseWriter) bool {\n    _, ok := w.(http.Hijacker)\n    return ok\n}","tryCatchPattern":"conn, rw, err := srw.Hijack()\nif err != nil {\n    if errors.Is(err, middleware.ErrHijackNotSupported) {\n        // degrade: respond normally instead of upgrading\n        http.Error(srw, \"upgrade unsupported\", http.StatusInternalServerError)\n        return\n    }\n    return err\n}","preventionTips":["Implement Hijack in every custom ResponseWriter wrapper by delegating to the inner writer","Keep WebSocket routes outside non-hijackable middleware chains","Use httptest.NewServer (not ResponseRecorder) for upgrade tests","Audit middleware order whenever adding logging/compression layers"],"tags":["http","websocket","hijack","middleware","gofr"],"backgroundTag":"hijack-not-supported","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}