6ccaae0573
Extract authenticate/probe-resistance to auth.go and roundTrip/forwarding to proxy.go, following the handler/http/ pattern. Export sentinel errors (ErrAuthFailed, ErrWrongConnType) for precise test assertions. Fix flushWriter panic recovery to handle non-string/non-error panics. Default HTTPS port to 443 when no port is specified in the Host header.
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package http2
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
type testFlusher struct {
|
|
bytes.Buffer
|
|
flushed bool
|
|
}
|
|
|
|
func (f *testFlusher) Flush() {
|
|
f.flushed = true
|
|
}
|
|
|
|
func TestFlushWriter_Write(t *testing.T) {
|
|
t.Run("normal write", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
fw := flushWriter{w: &buf}
|
|
n, err := fw.Write([]byte("hello"))
|
|
if err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
if n != 5 {
|
|
t.Errorf("n = %d, want 5", n)
|
|
}
|
|
if buf.String() != "hello" {
|
|
t.Errorf("buf = %q, want %q", buf.String(), "hello")
|
|
}
|
|
})
|
|
|
|
t.Run("write and flush", func(t *testing.T) {
|
|
tf := &testFlusher{}
|
|
fw := flushWriter{w: tf}
|
|
_, err := fw.Write([]byte("hello"))
|
|
if err != nil {
|
|
t.Fatalf("Write: %v", err)
|
|
}
|
|
if !tf.flushed {
|
|
t.Error("expected flush after write")
|
|
}
|
|
if tf.String() != "hello" {
|
|
t.Errorf("buf = %q, want %q", tf.String(), "hello")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestFlushWriter_PanicRecovery(t *testing.T) {
|
|
t.Run("string panic", func(t *testing.T) {
|
|
pw := &panicWriter{panicVal: "boom"}
|
|
fw := flushWriter{w: pw}
|
|
_, err := fw.Write([]byte("data"))
|
|
if err == nil {
|
|
t.Fatal("expected error from panic recovery")
|
|
}
|
|
if err.Error() != "boom" {
|
|
t.Errorf("err = %q, want %q", err.Error(), "boom")
|
|
}
|
|
})
|
|
|
|
t.Run("error panic", func(t *testing.T) {
|
|
pw := &panicWriter{panicVal: errors.New("err boom")}
|
|
fw := flushWriter{w: pw}
|
|
_, err := fw.Write([]byte("data"))
|
|
if err == nil {
|
|
t.Fatal("expected error from panic recovery")
|
|
}
|
|
if err.Error() != "err boom" {
|
|
t.Errorf("err = %q, want %q", err.Error(), "err boom")
|
|
}
|
|
})
|
|
|
|
t.Run("int panic", func(t *testing.T) {
|
|
pw := &panicWriter{panicVal: 42}
|
|
fw := flushWriter{w: pw}
|
|
_, err := fw.Write([]byte("data"))
|
|
if err == nil {
|
|
t.Fatal("expected error from panic recovery")
|
|
}
|
|
if err.Error() != "42" {
|
|
t.Errorf("err = %q, want %q", err.Error(), "42")
|
|
}
|
|
})
|
|
}
|
|
|
|
type panicWriter struct {
|
|
panicVal any
|
|
}
|
|
|
|
func (w *panicWriter) Write([]byte) (int, error) {
|
|
panic(w.panicVal)
|
|
}
|
|
|
|
func TestFlushWriter_ImplementsHTTPFlusher(t *testing.T) {
|
|
// flushWriter should allow the wrapped value to be used as http.Flusher.
|
|
tf := &testFlusher{}
|
|
fw := flushWriter{w: tf}
|
|
_, err := fw.Write([]byte("x"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !tf.flushed {
|
|
t.Error("expected Flush() to be called after Write()")
|
|
}
|
|
// Verify that testFlusher is recognized as http.Flusher.
|
|
var _ http.Flusher = tf
|
|
}
|