mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
* Fix WebSocket support by implementing Hijacker interface Add responsewriter.PassthroughWriter to preserve optional HTTP interfaces (Hijacker, Flusher, Pusher) when wrapping http.ResponseWriter in middleware. Without this delegation: - WebSocket connections fail (can't hijack the connection) - Streaming breaks (can't flush buffers) - HTTP/2 push doesn't work * Add HijackTracker to manage hijacked connections during graceful shutdown * Refactor HijackTracker to use middleware for tracking hijacked connections * Refactor server handler chain setup for improved readability and maintainability
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package responsewriter
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
// PassthroughWriter wraps an http.ResponseWriter and preserves optional
|
|
// interfaces like Hijacker, Flusher, and Pusher by delegating to the underlying
|
|
// ResponseWriter if it supports them.
|
|
//
|
|
// This is the standard pattern for Go middleware that needs to wrap ResponseWriter
|
|
// while maintaining support for protocol upgrades (WebSocket), streaming (Flusher),
|
|
// and HTTP/2 server push.
|
|
type PassthroughWriter struct {
|
|
http.ResponseWriter
|
|
}
|
|
|
|
// New creates a new wrapper around the given ResponseWriter.
|
|
func New(w http.ResponseWriter) *PassthroughWriter {
|
|
return &PassthroughWriter{ResponseWriter: w}
|
|
}
|
|
|
|
// Hijack implements http.Hijacker interface if the underlying ResponseWriter supports it.
|
|
// This is required for WebSocket connections and other protocol upgrades.
|
|
func (w *PassthroughWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
if hijacker, ok := w.ResponseWriter.(http.Hijacker); ok {
|
|
return hijacker.Hijack()
|
|
}
|
|
return nil, nil, http.ErrNotSupported
|
|
}
|
|
|
|
// Flush implements http.Flusher interface if the underlying ResponseWriter supports it.
|
|
func (w *PassthroughWriter) Flush() {
|
|
if flusher, ok := w.ResponseWriter.(http.Flusher); ok {
|
|
flusher.Flush()
|
|
}
|
|
}
|
|
|
|
// Push implements http.Pusher interface if the underlying ResponseWriter supports it.
|
|
func (w *PassthroughWriter) Push(target string, opts *http.PushOptions) error {
|
|
if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
|
|
return pusher.Push(target, opts)
|
|
}
|
|
return http.ErrNotSupported
|
|
}
|
|
|
|
// Unwrap returns the underlying ResponseWriter.
|
|
// This is required for http.ResponseController (Go 1.20+) to work correctly.
|
|
func (w *PassthroughWriter) Unwrap() http.ResponseWriter {
|
|
return w.ResponseWriter
|
|
}
|