mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 11:37:20 +08:00
100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
package server
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
type responseWrittenTracker interface {
|
|
ResponseWritten() bool
|
|
}
|
|
|
|
type trackedResponseWriter struct {
|
|
http.ResponseWriter
|
|
wroteHeader bool
|
|
statusCode int
|
|
}
|
|
|
|
func newTrackedResponseWriter(writer http.ResponseWriter) *trackedResponseWriter {
|
|
return &trackedResponseWriter{ResponseWriter: writer}
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) WriteHeader(statusCode int) {
|
|
if writer == nil || writer.ResponseWriter == nil {
|
|
return
|
|
}
|
|
if writer.wroteHeader {
|
|
return
|
|
}
|
|
writer.wroteHeader = true
|
|
writer.statusCode = statusCode
|
|
writer.ResponseWriter.WriteHeader(statusCode)
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) Write(payload []byte) (int, error) {
|
|
if writer == nil || writer.ResponseWriter == nil {
|
|
return 0, http.ErrAbortHandler
|
|
}
|
|
if !writer.wroteHeader {
|
|
writer.WriteHeader(http.StatusOK)
|
|
}
|
|
return writer.ResponseWriter.Write(payload)
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) Flush() {
|
|
if writer == nil || writer.ResponseWriter == nil {
|
|
return
|
|
}
|
|
if !writer.wroteHeader {
|
|
writer.WriteHeader(http.StatusOK)
|
|
}
|
|
if flusher, ok := writer.ResponseWriter.(http.Flusher); ok {
|
|
flusher.Flush()
|
|
}
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
if writer == nil || writer.ResponseWriter == nil {
|
|
return nil, nil, fmt.Errorf("response writer is nil")
|
|
}
|
|
hijacker, ok := writer.ResponseWriter.(http.Hijacker)
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("response writer does not support hijacking")
|
|
}
|
|
writer.wroteHeader = true
|
|
return hijacker.Hijack()
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) Unwrap() http.ResponseWriter {
|
|
if writer == nil {
|
|
return nil
|
|
}
|
|
return writer.ResponseWriter
|
|
}
|
|
|
|
func (writer *trackedResponseWriter) ResponseWritten() bool {
|
|
return writer != nil && writer.wroteHeader
|
|
}
|
|
|
|
func responseWriterHasWrittenHeader(writer http.ResponseWriter) bool {
|
|
for writer != nil {
|
|
if tracker, ok := writer.(responseWrittenTracker); ok {
|
|
if tracker.ResponseWritten() {
|
|
return true
|
|
}
|
|
}
|
|
unwrapper, ok := writer.(interface{ Unwrap() http.ResponseWriter })
|
|
if !ok {
|
|
return false
|
|
}
|
|
next := unwrapper.Unwrap()
|
|
if next == nil || next == writer {
|
|
return false
|
|
}
|
|
writer = next
|
|
}
|
|
return false
|
|
}
|