gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/gmhttp/alpn_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gmhttp_test 6 7 import ( 8 "bufio" 9 "bytes" 10 "fmt" 11 "io" 12 "strings" 13 "testing" 14 15 . "gitee.com/ks-custle/core-gm/gmhttp" 16 "gitee.com/ks-custle/core-gm/gmhttp/httptest" 17 tls "gitee.com/ks-custle/core-gm/gmtls" 18 "gitee.com/ks-custle/core-gm/x509" 19 ) 20 21 func TestNextProtoUpgrade(t *testing.T) { 22 setParallel(t) 23 defer afterTest(t) 24 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { 25 _, _ = fmt.Fprintf(w, "path=%s,proto=", r.URL.Path) 26 if r.TLS != nil { 27 _, _ = w.Write([]byte(r.TLS.NegotiatedProtocol)) 28 } 29 if r.RemoteAddr == "" { 30 t.Error("request with no RemoteAddr") 31 } 32 if r.Body == nil { 33 t.Errorf("request with nil Body") 34 } 35 })) 36 ts.TLS = &tls.Config{ 37 NextProtos: []string{"unhandled-proto", "tls-0.9"}, 38 } 39 ts.Config.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){ 40 "tls-0.9": handleTLSProtocol09, 41 } 42 ts.StartTLS() 43 defer ts.Close() 44 45 // Normal request, without NPN. 46 { 47 c := ts.Client() 48 res, err := c.Get(ts.URL) 49 if err != nil { 50 t.Fatal(err) 51 } 52 body, err := io.ReadAll(res.Body) 53 if err != nil { 54 t.Fatal(err) 55 } 56 if want := "path=/,proto="; string(body) != want { 57 t.Errorf("plain request = %q; want %q", body, want) 58 } 59 } 60 61 // Request to an advertised but unhandled NPN protocol. 62 // Server will hang up. 63 { 64 certPool := x509.NewCertPool() 65 certPool.AddCert(ts.Certificate()) 66 tr := &Transport{ 67 TLSClientConfig: &tls.Config{ 68 RootCAs: certPool, 69 NextProtos: []string{"unhandled-proto"}, 70 }, 71 } 72 defer tr.CloseIdleConnections() 73 c := &Client{ 74 Transport: tr, 75 } 76 res, err := c.Get(ts.URL) 77 if err == nil { 78 defer func(Body io.ReadCloser) { 79 _ = Body.Close() 80 }(res.Body) 81 var buf bytes.Buffer 82 _ = res.Write(&buf) 83 t.Errorf("expected error on unhandled-proto request; got: %s", buf.Bytes()) 84 } 85 } 86 87 // Request using the "tls-0.9" protocol, which we register here. 88 // It is HTTP/0.9 over TLS. 89 { 90 c := ts.Client() 91 tlsConfig := c.Transport.(*Transport).TLSClientConfig 92 tlsConfig.NextProtos = []string{"tls-0.9"} 93 conn, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig) 94 if err != nil { 95 t.Fatal(err) 96 } 97 _, _ = conn.Write([]byte("GET /foo\n")) 98 body, err := io.ReadAll(conn) 99 if err != nil { 100 t.Fatal(err) 101 } 102 if want := "path=/foo,proto=tls-0.9"; string(body) != want { 103 t.Errorf("plain request = %q; want %q", body, want) 104 } 105 } 106 } 107 108 // handleTLSProtocol09 implements the HTTP/0.9 protocol over TLS, for the 109 // TestNextProtoUpgrade test. 110 // 111 //goland:noinspection GoUnusedParameter 112 func handleTLSProtocol09(srv *Server, conn *tls.Conn, h Handler) { 113 br := bufio.NewReader(conn) 114 line, err := br.ReadString('\n') 115 if err != nil { 116 return 117 } 118 line = strings.TrimSpace(line) 119 path := strings.TrimPrefix(line, "GET ") 120 if path == line { 121 return 122 } 123 req, _ := NewRequest("GET", path, nil) 124 req.Proto = "HTTP/0.9" 125 req.ProtoMajor = 0 126 req.ProtoMinor = 9 127 rw := &http09Writer{conn, make(Header)} 128 h.ServeHTTP(rw, req) 129 } 130 131 type http09Writer struct { 132 io.Writer 133 h Header 134 } 135 136 func (w http09Writer) Header() Header { return w.h } 137 func (w http09Writer) WriteHeader(int) {} // no headers