diff --git a/README.md b/README.md index 8fcf1a3c9ba0a723e20efc16273f99b244dab9fa..a3a3aa2c1bf385790ff61c5df9705949253e5bcc 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,41 @@ variables: ``` $ go-httpbin -help Usage of go-httpbin: + -host string + Host to listen on (default "0.0.0.0") + -port int + Port to listen on (default 8080) + -https-cert-file string + HTTPS certificate file + -https-key-file string + HTTPS private key file -max-body-size int Maximum size of request or response, in bytes (default 1048576) -max-duration duration Maximum duration a response may take (default 10s) - -port int - Port to listen on (default 8080) + +Examples: + # Run http server + $ go-httpbin -host 127.0.0.1 -port 8081 + + # Run https server + + # Generate .crt and .key files + $ openssl genrsa -out server.key 2048 + $ openssl ecparam -genkey -name secp384r1 -out server.key + $ openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 + + $ go-httpbin -host 127.0.0.1 -port 8081 -https-cert-file ./server.crt -https-key-file ./server.key ``` Docker images are published to [Docker Hub][docker-hub]: ``` +# Run http server $ docker run -P mccutchen/go-httpbin + +# Run https server +$ docker run -e HTTPS_CERT_FILE='/tmp/server.crt' -e HTTPS_KEY_FILE='/tmp/server.key' -p 8080:8080 -v /tmp:/tmp mccutchen/go-httpbin ``` The `github.com/mccutchen/go-httpbin/httpbin` package can also be used as a diff --git a/cmd/go-httpbin/main.go b/cmd/go-httpbin/main.go index fecdcaf8a7cce31c7a0a107f1b817811ddc5a3f7..2b326549a76c3d93fc3132953fa49f081fb2da2f 100644 --- a/cmd/go-httpbin/main.go +++ b/cmd/go-httpbin/main.go @@ -1,6 +1,7 @@ package main import ( + "crypto/tls" "flag" "fmt" "log" @@ -13,16 +14,23 @@ import ( "github.com/mccutchen/go-httpbin/httpbin" ) +const defaultHost = "0.0.0.0" const defaultPort = 8080 var ( - port int - maxBodySize int64 - maxDuration time.Duration + host string + port int + maxBodySize int64 + maxDuration time.Duration + httpsCertFile string + httpsKeyFile string ) func main() { + flag.StringVar(&host, "host", defaultHost, "Host to listen on") flag.IntVar(&port, "port", defaultPort, "Port to listen on") + flag.StringVar(&httpsCertFile, "https-cert-file", "", "HTTPS Server certificate file") + flag.StringVar(&httpsKeyFile, "https-key-file", "", "HTTPS Server private key file") flag.Int64Var(&maxBodySize, "max-body-size", httpbin.DefaultMaxBodySize, "Maximum size of request or response, in bytes") flag.DurationVar(&maxDuration, "max-duration", httpbin.DefaultMaxDuration, "Maximum duration a response may take") flag.Parse() @@ -47,6 +55,9 @@ func main() { os.Exit(1) } } + if host == defaultHost && os.Getenv("HOST") != "" { + host = os.Getenv("HOST") + } if port == defaultPort && os.Getenv("PORT") != "" { port, err = strconv.Atoi(os.Getenv("PORT")) if err != nil { @@ -56,6 +67,13 @@ func main() { } } + if httpsCertFile == "" && os.Getenv("HTTPS_CERT_FILE") != "" { + httpsCertFile = os.Getenv("HTTPS_CERT_FILE") + } + if httpsKeyFile == "" && os.Getenv("HTTPS_KEY_FILE") != "" { + httpsKeyFile = os.Getenv("HTTPS_KEY_FILE") + } + logger := log.New(os.Stderr, "", 0) h := httpbin.New( @@ -64,7 +82,25 @@ func main() { httpbin.WithObserver(httpbin.StdLogObserver(logger)), ) - listenAddr := net.JoinHostPort("0.0.0.0", strconv.Itoa(port)) - logger.Printf("go-httpbin listening on %s", listenAddr) - http.ListenAndServe(listenAddr, h.Handler()) + listenAddr := net.JoinHostPort(host, strconv.Itoa(port)) + + server := &http.Server{ + Addr: listenAddr, + Handler: h.Handler(), + } + + if httpsCertFile != "" && httpsKeyFile != "" { + cert, err := tls.LoadX509KeyPair(httpsCertFile, httpsKeyFile) + if err != nil { + log.Fatal("Failed to generate https key pair: ", err) + } + server.TLSConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + } + logger.Printf("go-httpbin listening on https://%s", listenAddr) + server.ListenAndServeTLS("", "") + } else { + logger.Printf("go-httpbin listening on http://%s", listenAddr) + server.ListenAndServe() + } }