mirror of
https://github.com/golang/go.git
synced 2025-05-16 21:04:38 +00:00
After merging https://go-review.googlesource.com/c/34639/, it was pointed out to me that a lot of tests under net/http could use the new functionality to simplify and unify testing. Using the httptest.Server provided Client removes the need to call CloseIdleConnections() on all Transports created, as it is automatically called on the Transport associated with the client when Server.Close() is called. Change the transport used by the non-TLS httptest.Server to a new *http.Transport rather than using http.DefaultTransport implicitly. The TLS version already used its own *http.Transport. This change is to prevent concurrency problems with using DefaultTransport implicitly across several httptest.Server's. Add tests to ensure the httptest.Server.Client().Transport RoundTripper interface is implemented by a *http.Transport, as is now assumed across large parts of net/http tests. Change-Id: I9f9d15f59d72893deead5678d314388718c91821 Reviewed-on: https://go-review.googlesource.com/37771 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
134 lines
3.0 KiB
Go
134 lines
3.0 KiB
Go
// Copyright 2013 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package http_test
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
. "net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNextProtoUpgrade(t *testing.T) {
|
|
setParallel(t)
|
|
defer afterTest(t)
|
|
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
|
fmt.Fprintf(w, "path=%s,proto=", r.URL.Path)
|
|
if r.TLS != nil {
|
|
w.Write([]byte(r.TLS.NegotiatedProtocol))
|
|
}
|
|
if r.RemoteAddr == "" {
|
|
t.Error("request with no RemoteAddr")
|
|
}
|
|
if r.Body == nil {
|
|
t.Errorf("request with nil Body")
|
|
}
|
|
}))
|
|
ts.TLS = &tls.Config{
|
|
NextProtos: []string{"unhandled-proto", "tls-0.9"},
|
|
}
|
|
ts.Config.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){
|
|
"tls-0.9": handleTLSProtocol09,
|
|
}
|
|
ts.StartTLS()
|
|
defer ts.Close()
|
|
|
|
// Normal request, without NPN.
|
|
{
|
|
c := ts.Client()
|
|
res, err := c.Get(ts.URL)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if want := "path=/,proto="; string(body) != want {
|
|
t.Errorf("plain request = %q; want %q", body, want)
|
|
}
|
|
}
|
|
|
|
// Request to an advertised but unhandled NPN protocol.
|
|
// Server will hang up.
|
|
{
|
|
certPool := x509.NewCertPool()
|
|
certPool.AddCert(ts.Certificate())
|
|
tr := &Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
RootCAs: certPool,
|
|
NextProtos: []string{"unhandled-proto"},
|
|
},
|
|
}
|
|
defer tr.CloseIdleConnections()
|
|
c := &Client{
|
|
Transport: tr,
|
|
}
|
|
res, err := c.Get(ts.URL)
|
|
if err == nil {
|
|
defer res.Body.Close()
|
|
var buf bytes.Buffer
|
|
res.Write(&buf)
|
|
t.Errorf("expected error on unhandled-proto request; got: %s", buf.Bytes())
|
|
}
|
|
}
|
|
|
|
// Request using the "tls-0.9" protocol, which we register here.
|
|
// It is HTTP/0.9 over TLS.
|
|
{
|
|
c := ts.Client()
|
|
tlsConfig := c.Transport.(*Transport).TLSClientConfig
|
|
tlsConfig.NextProtos = []string{"tls-0.9"}
|
|
conn, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
conn.Write([]byte("GET /foo\n"))
|
|
body, err := ioutil.ReadAll(conn)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if want := "path=/foo,proto=tls-0.9"; string(body) != want {
|
|
t.Errorf("plain request = %q; want %q", body, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// handleTLSProtocol09 implements the HTTP/0.9 protocol over TLS, for the
|
|
// TestNextProtoUpgrade test.
|
|
func handleTLSProtocol09(srv *Server, conn *tls.Conn, h Handler) {
|
|
br := bufio.NewReader(conn)
|
|
line, err := br.ReadString('\n')
|
|
if err != nil {
|
|
return
|
|
}
|
|
line = strings.TrimSpace(line)
|
|
path := strings.TrimPrefix(line, "GET ")
|
|
if path == line {
|
|
return
|
|
}
|
|
req, _ := NewRequest("GET", path, nil)
|
|
req.Proto = "HTTP/0.9"
|
|
req.ProtoMajor = 0
|
|
req.ProtoMinor = 9
|
|
rw := &http09Writer{conn, make(Header)}
|
|
h.ServeHTTP(rw, req)
|
|
}
|
|
|
|
type http09Writer struct {
|
|
io.Writer
|
|
h Header
|
|
}
|
|
|
|
func (w http09Writer) Header() Header { return w.h }
|
|
func (w http09Writer) WriteHeader(int) {} // no headers
|