status-go/vendor/github.com/anacrolix/missinggo/v2/httpresponsestatus.go

77 lines
1.7 KiB
Go
Raw Normal View History

2022-03-10 09:44:48 +00:00
package missinggo
// todo move to httptoo as ResponseRecorder
import (
"bufio"
"net"
"net/http"
"time"
)
// A http.ResponseWriter that tracks the status of the response. The status
// code, and number of bytes written for example.
type StatusResponseWriter struct {
http.ResponseWriter
Code int
BytesWritten int64
Started time.Time
TimeToFirstByte time.Duration // Time to first byte
GotFirstByte bool
WroteHeader Event
Hijacked bool
}
var _ interface {
http.ResponseWriter
http.Hijacker
} = (*StatusResponseWriter)(nil)
func (me *StatusResponseWriter) Write(b []byte) (n int, err error) {
// Exactly how it's done in the standard library. This ensures Code is
// correct.
if !me.WroteHeader.IsSet() {
me.WriteHeader(http.StatusOK)
}
if me.Started.IsZero() {
panic("Started was not initialized")
}
timeBeforeWrite := time.Now()
n, err = me.ResponseWriter.Write(b)
if n > 0 && !me.GotFirstByte {
me.TimeToFirstByte = timeBeforeWrite.Sub(me.Started)
me.GotFirstByte = true
}
me.BytesWritten += int64(n)
return
}
func (me *StatusResponseWriter) WriteHeader(code int) {
me.ResponseWriter.WriteHeader(code)
if !me.WroteHeader.IsSet() {
me.Code = code
me.WroteHeader.Set()
}
}
func (me *StatusResponseWriter) Hijack() (c net.Conn, b *bufio.ReadWriter, err error) {
me.Hijacked = true
c, b, err = me.ResponseWriter.(http.Hijacker).Hijack()
if b.Writer.Buffered() != 0 {
panic("unexpected buffered writes")
}
c = responseConn{c, me}
return
}
type responseConn struct {
net.Conn
s *StatusResponseWriter
}
func (me responseConn) Write(b []byte) (n int, err error) {
n, err = me.Conn.Write(b)
me.s.BytesWritten += int64(n)
return
}