| // 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" | 
 | 	"fmt" | 
 | 	"io" | 
 | 	"io/ioutil" | 
 | 	. "net/http" | 
 | 	"net/http/httptest" | 
 | 	"strings" | 
 | 	"testing" | 
 | ) | 
 |  | 
 | func TestNextProtoUpgrade(t *testing.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. | 
 | 	{ | 
 | 		tr := newTLSTransport(t, ts) | 
 | 		defer tr.CloseIdleConnections() | 
 | 		c := &Client{Transport: tr} | 
 |  | 
 | 		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. | 
 | 	{ | 
 | 		tr := newTLSTransport(t, ts) | 
 | 		tr.TLSClientConfig.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. | 
 | 	{ | 
 | 		tlsConfig := newTLSTransport(t, ts).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 |