From 5e9b67bf0f4e53394057ea5a4c329997979d8f3c Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 26 Feb 2023 15:56:05 -0800 Subject: [PATCH] streaming client mode --- README.md | 13 +++++++++++++ h2cli.go | 22 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cbf1ecd..1d210f1 100644 --- a/README.md +++ b/README.md @@ -136,3 +136,16 @@ User-Agent: Go-http-client/2.0 body: ``` + +### Streaming mode: + +First prints foo, then bar after 3 second: +(assumes fortio server including https://github.com/fortio/fortio/pull/721 ie 1.53+) + +``` +(echo "foo"; sleep 3; echo "bar") | go run . -stream -url localhost:8080 +15:53:30 I h2c GET on http://localhost:8080 +foo +bar +15:53:33 I Response code 200, proto HTTP/2.0, size 8 +``` diff --git a/h2cli.go b/h2cli.go index 6c10fee..f224487 100644 --- a/h2cli.go +++ b/h2cli.go @@ -1,3 +1,9 @@ +// Copyright 2023 Fortio Authors +// License: Apache 2.0 +// +// Feel free to inspire (copy) from this code but linking back to +// https://github.com/fortio would be appreciated. + package main import ( @@ -23,6 +29,7 @@ var ( method = flag.String("method", "GET", "HTTP method to use") caCert = flag.String("cacert", "", "`Path` to a custom CA certificate file instead standard internet/system CAs") + stream = flag.Bool("stream", false, "stream stdin to server and back (h2 mode only)") ) func main() { @@ -72,7 +79,11 @@ func main() { } log.Infof("%s%s on %s", h2c, *method, *urlFlag) // Perform the request - req, err := http.NewRequestWithContext(context.Background(), *method, *urlFlag, nil) + var bodyReader io.Reader + if *stream { + bodyReader = os.Stdin + } + req, err := http.NewRequestWithContext(context.Background(), *method, *urlFlag, bodyReader) if err != nil { log.Fatalf("Request method %q url %q error: %v", *method, *urlFlag, err) } @@ -80,6 +91,15 @@ func main() { if err != nil { log.Fatalf("Failed %q %q - error: %v", *method, *urlFlag, err) } + if *stream { + n, err := io.Copy(os.Stdout, resp.Body) + log.Infof("Response code %d, proto %s, size %d", resp.StatusCode, resp.Proto, n) + if err != nil { + log.Fatalf("Error copying response body: %v", err) + } + return + } + // else, traditional read all reply mode body, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil {