github.com/MerlinKodo/quic-go@v0.39.2/example/client/main.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "bytes" 6 "context" 7 "crypto/tls" 8 "crypto/x509" 9 "flag" 10 "fmt" 11 "io" 12 "log" 13 "net/http" 14 "os" 15 "sync" 16 17 "github.com/MerlinKodo/quic-go" 18 "github.com/MerlinKodo/quic-go/http3" 19 "github.com/MerlinKodo/quic-go/internal/testdata" 20 "github.com/MerlinKodo/quic-go/internal/utils" 21 "github.com/MerlinKodo/quic-go/logging" 22 "github.com/MerlinKodo/quic-go/qlog" 23 ) 24 25 func main() { 26 verbose := flag.Bool("v", false, "verbose") 27 quiet := flag.Bool("q", false, "don't print the data") 28 keyLogFile := flag.String("keylog", "", "key log file") 29 insecure := flag.Bool("insecure", false, "skip certificate verification") 30 enableQlog := flag.Bool("qlog", false, "output a qlog (in the same directory)") 31 flag.Parse() 32 urls := flag.Args() 33 34 logger := utils.DefaultLogger 35 36 if *verbose { 37 logger.SetLogLevel(utils.LogLevelDebug) 38 } else { 39 logger.SetLogLevel(utils.LogLevelInfo) 40 } 41 logger.SetLogTimeFormat("") 42 43 var keyLog io.Writer 44 if len(*keyLogFile) > 0 { 45 f, err := os.Create(*keyLogFile) 46 if err != nil { 47 log.Fatal(err) 48 } 49 defer f.Close() 50 keyLog = f 51 } 52 53 pool, err := x509.SystemCertPool() 54 if err != nil { 55 log.Fatal(err) 56 } 57 testdata.AddRootCA(pool) 58 59 var qconf quic.Config 60 if *enableQlog { 61 qconf.Tracer = func(ctx context.Context, p logging.Perspective, connID quic.ConnectionID) *logging.ConnectionTracer { 62 filename := fmt.Sprintf("client_%x.qlog", connID) 63 f, err := os.Create(filename) 64 if err != nil { 65 log.Fatal(err) 66 } 67 log.Printf("Creating qlog file %s.\n", filename) 68 return qlog.NewConnectionTracer(utils.NewBufferedWriteCloser(bufio.NewWriter(f), f), p, connID) 69 } 70 } 71 roundTripper := &http3.RoundTripper{ 72 TLSClientConfig: &tls.Config{ 73 RootCAs: pool, 74 InsecureSkipVerify: *insecure, 75 KeyLogWriter: keyLog, 76 }, 77 QuicConfig: &qconf, 78 } 79 defer roundTripper.Close() 80 hclient := &http.Client{ 81 Transport: roundTripper, 82 } 83 84 var wg sync.WaitGroup 85 wg.Add(len(urls)) 86 for _, addr := range urls { 87 logger.Infof("GET %s", addr) 88 go func(addr string) { 89 rsp, err := hclient.Get(addr) 90 if err != nil { 91 log.Fatal(err) 92 } 93 logger.Infof("Got response for %s: %#v", addr, rsp) 94 95 body := &bytes.Buffer{} 96 _, err = io.Copy(body, rsp.Body) 97 if err != nil { 98 log.Fatal(err) 99 } 100 if *quiet { 101 logger.Infof("Response Body: %d bytes", body.Len()) 102 } else { 103 logger.Infof("Response Body:") 104 logger.Infof("%s", body.Bytes()) 105 } 106 wg.Done() 107 }(addr) 108 } 109 wg.Wait() 110 }