~james/core

core/spindle/http_server_test.go -rw-r--r-- 2.0 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 14 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package spindle

import (
	"io"
	"net"
	"net/http"
	"testing"
	"time"

	"github.com/gorilla/websocket"
)

func TestHTTPServerDropsSlowClientsButNotWebsockets(t *testing.T) {
	var upgrader websocket.Upgrader
	mux := http.NewServeMux()
	mux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			return
		}
		defer conn.Close()
		for {
			typ, msg, err := conn.ReadMessage()
			if err != nil || conn.WriteMessage(typ, msg) != nil {
				return
			}
		}
	})

	srv := newHTTPServer("", mux)
	if srv.ReadHeaderTimeout <= 0 || srv.ReadTimeout <= 0 || srv.IdleTimeout <= 0 {
		t.Fatalf("timeouts header=%v read=%v idle=%v, want all set", srv.ReadHeaderTimeout, srv.ReadTimeout, srv.IdleTimeout)
	}
	// the real timeouts are too long to sit through in a test
	srv.ReadHeaderTimeout = 200 * time.Millisecond
	srv.ReadTimeout = 400 * time.Millisecond
	srv.IdleTimeout = 400 * time.Millisecond
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	go srv.Serve(ln)
	t.Cleanup(func() { srv.Close() })

	slow, err := net.Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer slow.Close()
	if _, err := slow.Write([]byte("GET /ws HTTP/1.1\r\nHost: spindle\r\n")); err != nil {
		t.Fatal(err)
	}
	slow.SetReadDeadline(time.Now().Add(3 * time.Second))
	if _, err := io.ReadAll(slow); err != nil {
		t.Fatalf("a connection that never finished its headers was still open after 3s: %v", err)
	}

	conn, _, err := websocket.DefaultDialer.Dial("ws://"+ln.Addr().String()+"/ws", nil)
	if err != nil {
		t.Fatal(err)
	}
	defer conn.Close()
	for _, pause := range []time.Duration{0, time.Second} {
		time.Sleep(pause)
		if err := conn.WriteMessage(websocket.TextMessage, []byte("ping")); err != nil {
			t.Fatalf("websocket write after %v: %v", pause, err)
		}
		conn.SetReadDeadline(time.Now().Add(2 * time.Second))
		if _, _, err := conn.ReadMessage(); err != nil {
			t.Fatalf("websocket echo after %v: %v, want it to outlive ReadTimeout", pause, err)
		}
	}
}