func TestServeWithSlashRedirectKeepsQueryString(t *testing.T) {
	setParallel(t)
	defer afterTest(t)
	writeBackQuery := func(w ResponseWriter, r *Request) {
		fmt.Fprintf(w, "%s", r.URL.RawQuery)
	}
	mux := NewServeMux()
	mux.HandleFunc("/testOne", writeBackQuery)
	mux.HandleFunc("/testTwo/", writeBackQuery)
	mux.HandleFunc("/testThree", writeBackQuery)
	mux.HandleFunc("/testThree/", func(w ResponseWriter, r *Request) {
		fmt.Fprintf(w, "%s:bar", r.URL.RawQuery)
	})
	ts := httptest.NewServer(mux)
	defer ts.Close()
	tests := [...]struct {
		path     string
		method   string
		want     string
		statusOk bool
	}{
		0: {"/testOne?this=that", "GET", "this=that", true},
		1: {"/testTwo?foo=bar", "GET", "foo=bar", true},
		2: {"/testTwo?a=1&b=2&a=3", "GET", "a=1&b=2&a=3", true},
		3: {"/testTwo?", "GET", "", true},
		4: {"/testThree?foo", "GET", "foo", true},
		5: {"/testThree/?foo", "GET", "foo:bar", true},
		6: {"/testThree?foo", "CONNECT", "foo", true},
		7: {"/testThree/?foo", "CONNECT", "foo:bar", true},
		8: {"/testOne/foo/..?foo", "GET", "foo", true},
		9: {"/testOne/foo/..?foo", "CONNECT", "404 page not found\n", false},
	}
	for i, tt := range tests {
		req, _ := NewRequest(tt.method, ts.URL+tt.path, nil)
		res, err := ts.Client().Do(req)
		if err != nil {
			continue
		}
		slurp, _ := ioutil.ReadAll(res.Body)
		res.Body.Close()
		if !tt.statusOk {
			if got, want := res.StatusCode, 404; got != want {
				t.Errorf("#%d: Status = %d; want = %d", i, got, want)
			}
		}
		if got, want := string(slurp), tt.want; got != want {
			t.Errorf("#%d: Body = %q; want = %q", i, got, want)
		}
	}
}
Test that the special cased "/route" redirect
implicitly created by a registered "/route/"
properly sets the query string in the redirect URL.
See Issue 17841.
package http_test
import (
	"bufio"
	"bytes"
	"compress/gzip"
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"internal/testenv"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	. "net/http"
	"net/http/httptest"
	"net/http/httputil"
	"net/http/internal"
	"net/url"
	"os"
	"os/exec"
	"reflect"
	"runtime"
	"runtime/debug"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"testing"
	"time"
)
type dummyAddr string
type oneConnListener struct {
	conn net.Conn
}
func (l *oneConnListener) Accept() (c net.Conn, err error) {
	c = l.conn
	if c == nil {
		err = io.EOF
		return
	}
	err = nil
	l.conn = nil
	return
}
func (l *oneConnListener) Close() error {
	return nil
}
func (l *oneConnListener) Addr() net.Addr {
	return dummyAddr("test-address")
}
func (a dummyAddr) Network() string {
	return string(a)
}
func (a dummyAddr) String() string {
	return string(a)
}
type noopConn struct{}
func (noopConn) LocalAddr() net.Addr                { return dummyAddr("local-addr") }
func (noopConn) RemoteAddr() net.Addr               { return dummyAddr("remote-addr") }
func (noopConn) SetDeadline(t time.Time) error      { return nil }
func (noopConn) SetReadDeadline(t time.Time) error  { return nil }
func (noopConn) SetWriteDeadline(t time.Time) error { return nil }
type rwTestConn struct {
	io.Reader
	io.Writer
	noopConn
	closeFunc func() error  
	closec    chan bool     
}
func (c *rwTestConn) Close() error {
	if c.closeFunc != nil {
		return c.closeFunc()
	}
	select {
	case c.closec <- true:
	default:
	}
	return nil
}
type testConn struct {
	readMu   sync.Mutex  
	readBuf  bytes.Buffer
	writeBuf bytes.Buffer
	closec   chan bool  
	noopConn
}
func (c *testConn) Read(b []byte) (int, error) {
	c.readMu.Lock()
	defer c.readMu.Unlock()
	return c.readBuf.Read(b)
}
func (c *testConn) Write(b []byte) (int, error) {
	return c.writeBuf.Write(b)
}
func (c *testConn) Close() error {
	select {
	case c.closec <- true:
	default:
	}
	return nil
}
func reqBytes(req string) []byte {
	return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
}
type handlerTest struct {
	logbuf  bytes.Buffer
	handler Handler
}
func newHandlerTest(h Handler) handlerTest {
	return handlerTest{handler: h}
}
func (ht *handlerTest) rawResponse(req string) string {
	reqb := reqBytes(req)
	var output bytes.Buffer
	conn := &rwTestConn{
		Reader: bytes.NewReader(reqb),
		Writer: &output,
		closec: make(chan bool, 1),
	}
	ln := &oneConnListener{conn: conn}
	srv := &Server{
		ErrorLog: log.New(&ht.logbuf, "", 0),
		Handler:  ht.handler,
	}
	go srv.Serve(ln)
	<-conn.closec
	return output.String()
}
func TestConsumingBodyOnNextConn(t *testing.T) {
	t.Parallel()
	defer afterTest(t)
	conn := new(testConn)
	for i := 0; i < 2; i++ {
		conn.readBuf.Write([]byte(
			"POST / HTTP/1.1\r\n" +
				"Host: test\r\n" +
				"Content-Length: 11\r\n" +
				"\r\n" +
				"foo=1&bar=1"))
	}
	reqNum := 0
	ch := make(chan *Request)
	servech := make(chan error)
	listener := &oneConnListener{conn}
	handler := func(res ResponseWriter, req *Request) {
		reqNum++
		ch <- req
	}
	go func() {
		servech <- Serve(listener, HandlerFunc(handler))
	}()
	var req *Request
	req = <-ch
	if req == nil {
		t.Fatal("Got nil first request.")
	}
	if req.Method != "POST" {
		t.Errorf("For request #1's method, got %q; expected %q",
			req.Method, "POST")
	}
	req = <-ch
	if req == nil {
		t.Fatal("Got nil first request.")
	}
	if req.Method != "POST" {
		t.Errorf("For request #2's method, got %q; expected %q",
			req.Method, "POST")
	}
	if serveerr := <-servech; serveerr != io.EOF {
		t.Errorf("Serve returned %q; expected EOF", serveerr)
	}
}
type stringHandler string
func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
	w.Header().Set("Result", string(s))
}
var handlers = []struct {
	pattern string
	msg     string
}{
	{"/", "Default"},
	{"/someDir/", "someDir"},
	{"/#/", "hash"},
	{"someHost.com/someDir/", "someHost.com/someDir"},
}
var vtests = []struct {
	url      string
	expected string
}{
	{"http://localhost/someDir/apage", "someDir"},
	{"http://localhost/%23/apage", "hash"},
	{"http://localhost/otherDir/apage", "Default"},
	{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
	{"http://otherHost.com/someDir/apage", "someDir"},
	{"http://otherHost.com/aDir/apage", "Default"},
	{"http://localhost/someDir", "/someDir/"},
	{"http://localhost/%23", "/%23/"},
	{"http://someHost.com/someDir", "/someDir/"},
}
func TestHostHandlers(t *testing.T) {
	setParallel(t)
	defer afterTest(t)
	mux := NewServeMux()
	for _, h := range handlers {
		mux.Handle(h.pattern, stringHandler(h.msg))
	}
	ts := httptest.NewServer(mux)
	defer ts.Close()
	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer conn.Close()
	cc := httputil.NewClientConn(conn, nil)
	for _, vt := range vtests {
		var r *Response
		var req Request
		if req.URL, err = url.Parse(vt.url); err != nil {
			t.Errorf("cannot parse url: %v", err)
			continue
		}
		if err := cc.Write(&req); err != nil {
			t.Errorf("writing request: %v", err)
			continue
		}
		r, err := cc.Read(&req)
		if err != nil {
			t.Errorf("reading response: %v", err)
			continue
		}
		switch r.StatusCode {
		case StatusOK:
			s := r.Header.Get("Result")
			if s != vt.expected {
				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
			}
		case StatusMovedPermanently:
			s := r.Header.Get("Location")
			if s != vt.expected {
				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
			}
		default:
			t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
		}
	}
}
var serveMuxRegister = []struct {
	pattern string
	h       Handler
}{
	{"/dir/", serve(200)},
	{"/search", serve(201)},
	{"codesearch.google.com/search", serve(202)},
	{"codesearch.google.com/", serve(203)},
	{"example.com/", HandlerFunc(checkQueryStringHandler)},
}
func serve(code int) HandlerFunc {
	return func(w ResponseWriter, r *Request) {
		w.WriteHeader(code)
	}
}
func checkQueryStringHandler(w ResponseWriter, r *Request) {
	u := *r.URL
	u.Scheme = "http"
	u.Host = r.Host
	u.RawQuery = ""
	if "http://"+r.URL.RawQuery == u.String() {
		w.WriteHeader(200)
	} else {
		w.WriteHeader(500)
	}
}
var serveMuxTests = []struct {
	method  string
	host    string
	path    string
	code    int
	pattern string
}{
	{"GET", "google.com", "/", 404, ""},
	{"GET", "google.com", "/dir", 301, "/dir/"},
	{"GET", "google.com", "/dir/", 200, "/dir/"},
	{"GET", "google.com", "/dir/file", 200, "/dir/"},
	{"GET", "google.com", "/search", 201, "/search"},
	{"GET", "google.com", "/search/", 404, ""},
	{"GET", "google.com", "/search/foo", 404, ""},
	{"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
	{"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
	{"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
	{"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
	{"GET", "codesearch.google.com:443", "/", 203, "codesearch.google.com/"},
	{"GET", "images.google.com", "/search", 201, "/search"},
	{"GET", "images.google.com", "/search/", 404, ""},
	{"GET", "images.google.com", "/search/foo", 404, ""},
	{"GET", "google.com", "/../search", 301, "/search"},
	{"GET", "google.com", "/dir/..", 301, ""},
	{"GET", "google.com", "/dir/..", 301, ""},
	{"GET", "google.com", "/dir/./file", 301, "/dir/"},
	{"CONNECT", "google.com", "/dir", 301, "/dir/"},
	{"CONNECT", "google.com", "/../search", 404, ""},
	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
	{"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
}
func TestServeMuxHandler(t *testing.T) {
	setParallel(t)
	mux := NewServeMux()
	for _, e := range serveMuxRegister {
		mux.Handle(e.pattern, e.h)
	}
	for _, tt := range serveMuxTests {
		r := &Request{
			Method: tt.method,
			Host:   tt.host,
			URL: &url.URL{
				Path: tt.path,
			},
		}
		h, pattern := mux.Handler(r)
		rr := httptest.NewRecorder()
		h.ServeHTTP(rr, r)
		if pattern != tt.pattern || rr.Code != tt.code {
			t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern)
		}
	}
}
func TestServeMuxHandleFuncWithNilHandler(t *testing.T) {
	setParallel(t)
	defer func() {
		if err := recover(); err == nil {
			t.Error("expected call to mux.HandleFunc to panic")
		}
	}()
	mux := NewServeMux()
	mux.HandleFunc("/", nil)
}
var serveMuxTests2 = []struct {
	method  string
	host    string
	url     string
	code    int
	redirOk bool
}{
	{"GET", "google.com", "/", 404, false},
	{"GET", "example.com", "/test/?example.com/test/", 200, false},
	{"GET", "example.com", "test/?example.com/test/", 200, true},
}
func TestServeMuxHandlerRedirects(t *testing.T) {
	setParallel(t)
	mux := NewServeMux()
	for _, e := range serveMuxRegister {
		mux.Handle(e.pattern, e.h)
	}
	for _, tt := range serveMuxTests2 {
		tries := 1  
		turl := tt.url
		for {
			u, e := url.Parse(turl)
			if e != nil {
				t.Fatal(e)
			}
			r := &Request{
				Method: tt.method,
				Host:   tt.host,
				URL:    u,
			}
			h, _ := mux.Handler(r)
			rr := httptest.NewRecorder()
			h.ServeHTTP(rr, r)
			if rr.Code != 301 {
				if rr.Code != tt.code {
					t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code)
				}
				break
			}
			if !tt.redirOk {
				t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url)
				break
			}
			turl = rr.HeaderMap.Get("Location")
			tries--
		}
		if tries < 0 {
			t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url)
		}
	}
}
func TestMuxRedirectLeadingSlashes(t *testing.T) {
	setParallel(t)
	paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
	for _, path := range paths {
		req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
		if err != nil {
			t.Errorf("%s", err)
		}
		mux := NewServeMux()
		resp := httptest.NewRecorder()
		mux.ServeHTTP(resp, req)
		if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
			t.Errorf("Expected Location header set to %q; got %q", expected, loc)
			return
		}
		if code, expected := resp.Code, StatusMovedPermanently; code != expected {
			t.Errorf("Expected response code of StatusMovedPermanently; got %d", code)
			return
		}
	}
}