gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/http2/transport_go117_test.go (about)

     1  // Copyright 2021 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  //go:build go1.17
     6  // +build go1.17
     7  
     8  package http2
     9  
    10  import (
    11  	"context"
    12  	"errors"
    13  
    14  	"gitee.com/ks-custle/core-gm/gmhttp/httptest"
    15  
    16  	http "gitee.com/ks-custle/core-gm/gmhttp"
    17  
    18  	tls "gitee.com/ks-custle/core-gm/gmtls"
    19  
    20  	"testing"
    21  )
    22  
    23  func TestTransportDialTLSContext(t *testing.T) {
    24  	blockCh := make(chan struct{})
    25  	serverTLSConfigFunc := func(ts *httptest.Server) {
    26  		ts.Config.TLSConfig = &tls.Config{
    27  			// Triggers the server to request the clients certificate
    28  			// during TLS handshake.
    29  			ClientAuth: tls.RequestClientCert,
    30  		}
    31  	}
    32  	ts := newServerTester(t,
    33  		func(w http.ResponseWriter, r *http.Request) {},
    34  		optOnlyServer,
    35  		serverTLSConfigFunc,
    36  	)
    37  	defer ts.Close()
    38  	tr := &Transport{
    39  		TLSClientConfig: &tls.Config{
    40  			GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) {
    41  				// Tests that the context provided to `req` is
    42  				// passed into this function.
    43  				close(blockCh)
    44  				<-cri.Context().Done()
    45  				return nil, cri.Context().Err()
    46  			},
    47  			InsecureSkipVerify: true,
    48  		},
    49  	}
    50  	defer tr.CloseIdleConnections()
    51  	req, err := http.NewRequest(http.MethodGet, ts.ts.URL, nil)
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  	ctx, cancel := context.WithCancel(context.Background())
    56  	defer cancel()
    57  	req = req.WithContext(ctx)
    58  	errCh := make(chan error)
    59  	go func() {
    60  		defer close(errCh)
    61  		res, err := tr.RoundTrip(req)
    62  		if err != nil {
    63  			errCh <- err
    64  			return
    65  		}
    66  		res.Body.Close()
    67  	}()
    68  	// Wait for GetClientCertificate handler to be called
    69  	<-blockCh
    70  	// Cancel the context
    71  	cancel()
    72  	// Expect the cancellation error here
    73  	err = <-errCh
    74  	if err == nil {
    75  		t.Fatal("cancelling context during client certificate fetch did not error as expected")
    76  		return
    77  	}
    78  	if !errors.Is(err, context.Canceled) {
    79  		t.Fatalf("unexpected error returned after cancellation: %v", err)
    80  	}
    81  }
    82  
    83  // TestDialRaceResumesDial tests that, given two concurrent requests
    84  // to the same address, when the first Dial is interrupted because
    85  // the first request's context is cancelled, the second request
    86  // resumes the dial automatically.
    87  func TestDialRaceResumesDial(t *testing.T) {
    88  	blockCh := make(chan struct{})
    89  	serverTLSConfigFunc := func(ts *httptest.Server) {
    90  		ts.Config.TLSConfig = &tls.Config{
    91  			// Triggers the server to request the clients certificate
    92  			// during TLS handshake.
    93  			ClientAuth: tls.RequestClientCert,
    94  		}
    95  	}
    96  	ts := newServerTester(t,
    97  		func(w http.ResponseWriter, r *http.Request) {},
    98  		optOnlyServer,
    99  		serverTLSConfigFunc,
   100  	)
   101  	defer ts.Close()
   102  	tr := &Transport{
   103  		TLSClientConfig: &tls.Config{
   104  			GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) {
   105  				select {
   106  				case <-blockCh:
   107  					// If we already errored, return without error.
   108  					return &tls.Certificate{}, nil
   109  				default:
   110  				}
   111  				close(blockCh)
   112  				<-cri.Context().Done()
   113  				return nil, cri.Context().Err()
   114  			},
   115  			InsecureSkipVerify: true,
   116  		},
   117  	}
   118  	defer tr.CloseIdleConnections()
   119  	req, err := http.NewRequest(http.MethodGet, ts.ts.URL, nil)
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	// Create two requests with independent cancellation.
   124  	ctx1, cancel1 := context.WithCancel(context.Background())
   125  	defer cancel1()
   126  	req1 := req.WithContext(ctx1)
   127  	ctx2, cancel2 := context.WithCancel(context.Background())
   128  	defer cancel2()
   129  	req2 := req.WithContext(ctx2)
   130  	errCh := make(chan error)
   131  	go func() {
   132  		res, err := tr.RoundTrip(req1)
   133  		if err != nil {
   134  			errCh <- err
   135  			return
   136  		}
   137  		res.Body.Close()
   138  	}()
   139  	successCh := make(chan struct{})
   140  	go func() {
   141  		// Don't start request until first request
   142  		// has initiated the handshake.
   143  		<-blockCh
   144  		res, err := tr.RoundTrip(req2)
   145  		if err != nil {
   146  			errCh <- err
   147  			return
   148  		}
   149  		res.Body.Close()
   150  		// Close successCh to indicate that the second request
   151  		// made it to the server successfully.
   152  		close(successCh)
   153  	}()
   154  	// Wait for GetClientCertificate handler to be called
   155  	<-blockCh
   156  	// Cancel the context first
   157  	cancel1()
   158  	// Expect the cancellation error here
   159  	err = <-errCh
   160  	if err == nil {
   161  		t.Fatal("cancelling context during client certificate fetch did not error as expected")
   162  		return
   163  	}
   164  	if !errors.Is(err, context.Canceled) {
   165  		t.Fatalf("unexpected error returned after cancellation: %v", err)
   166  	}
   167  	select {
   168  	case err := <-errCh:
   169  		t.Fatalf("unexpected second error: %v", err)
   170  	case <-successCh:
   171  	}
   172  }