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  }