/* Command http2client tests HTTP2 client request muliplexing of concurrent requests to the same service. */ package main import ( "crypto/tls" "log" "net/http" "net/http/httptrace" "net/url" "os" ) var ( //Mutual Auth HTTP Client client http.Client //Trace Context clientTrace = httptrace.ClientTrace{GetConn: getConn, GotConn: gotConn, PutIdleConn: putIdleConn, GotFirstResponseByte: gotFirstResponseByte, Got100Continue: got100Continue, DNSStart: dnsStart, DNSDone: dnsDone, ConnectStart: connectStart, ConnectDone: connectDone, TLSHandshakeStart: tlsHandshakeStart, TLSHandshakeDone: tlsHandshakeDone, WroteHeaders: wroteHeaders, Wait100Continue: wait100Continue, WroteRequest: wroteRequest} ) //HTTP Trace hooks func getConn(s string) { log.Printf("GetCon %s\n", s) } func gotConn(p httptrace.GotConnInfo) { log.Printf("gotConn %+v\n", p) } func putIdleConn(err error) { log.Printf("putIdleConn\n") } func gotFirstResponseByte() { log.Printf("gotFirstResponseByte\n") } func got100Continue() { log.Printf("got100Continue\n") } func dnsStart(p httptrace.DNSStartInfo) { log.Printf("dnsStart %+v\n", p) } func dnsDone(p httptrace.DNSDoneInfo) { log.Printf("dnsDone %+v\n", p) } func connectStart(network, addr string) { log.Printf("connectStart %s: %s\n", network, addr) } func connectDone(network, addr string, err error) { log.Printf("connectDone %s: %s\n", network, addr) } func tlsHandshakeStart() { log.Printf("tlsHandshakeStart\n") } func tlsHandshakeDone(conState tls.ConnectionState, err error) { log.Printf("tlsHandshakeDone %+v\n", conState) } func wroteHeaders() { log.Printf("wroteHeaders\n") } func wait100Continue() { log.Printf("wait100Continue\n") } func wroteRequest(wri httptrace.WroteRequestInfo) { log.Printf("wroteRequest\n") } func request(ch chan int) { var ( req http.Request rsp *http.Response err error ) req.Method = http.MethodGet req.URL, _ = url.ParseRequestURI("https://http2.golang.org/file/gopher.png") tracedReq := req.WithContext(httptrace.WithClientTrace(req.Context(), &clientTrace)) rsp, err = client.Do(tracedReq) if err != nil { log.Printf("Ping error: %s\n", err) os.Exit(1) } if rsp.StatusCode != http.StatusOK { log.Printf("Ping status: %s\n", rsp.Status) os.Exit(1) } //Signal request has completed ch <- 1 } //request func main() { var ( requestCh chan int requestDoneCnt int ) //Execute three concurrent requests to verify request multiplexing on the cached controller conection requestCh = make(chan int, 100) go request(requestCh) go request(requestCh) go request(requestCh) gatherPings: for { select { case <-requestCh: requestDoneCnt += 1 if requestDoneCnt >= 3 { break gatherPings } } } }