Skip to content

Commit

Permalink
Add option to activate HTTPS and HTTP/2 if client supports it
Browse files Browse the repository at this point in the history
This adds a new `-https` command line option to stripe-mock. When
enabled, it comes up serving HTTPS using a self-signed certificate
that's bundled into the executable.

Go supports serving HTTP/2 almost automatically from `net/http` with
HTTPS is activated, so clients that support HTTP/2 can test with it with
stripe-mock. The server will fallback to HTTP automatically for clients
that don't.

I figure this will be handy testing HTTP/2 support in our various client
libraries because it's easy to have stripe-mock spit out debug lines
that tell us that HTTP/2 has been activated correctly.
  • Loading branch information
brandur committed Jul 18, 2018
1 parent a58f08c commit bf95191
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 7 deletions.
56 changes: 52 additions & 4 deletions bindata.go

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions cert/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Cert

This directory contains a self-signed certificate for
localhost so that stripe-mock can run with HTTPS. You can
generate a new one with this command:

openssl req -x509 -newkey rsa:4096 -keyout cert/key.pem -out cert/cert.pem -days 3650 -nodes -subj '/CN=localhost'

And because certificates are bundled with the executable,
you'll need to put the new certificate into a `*.go` file
with go-bindata:

go generate
27 changes: 27 additions & 0 deletions cert/cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEpDCCAowCCQDtPflm0eRwCTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMTgwNzE3MjA0NzAzWhcNMjgwNzE0MjA0NzAzWjAUMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDB
XUN89XAuVYoui76SlFqIT4K5LIJrMsMFz3RU6kPWj2HSCB6P4wrmFhVwmziHkE0T
KUbyuX9J4ImR3WBgLdXiBX/uo8B0aAlRQTrqFkFWTYuWJvLEGopLEQVyKpgyJtuC
y0K6oM1h2SMqpphEpfY/x4GmSTkuSUwYcQsEorK6R0anjPtJBvRNm/17/dililW6
9ptaAoE71NVoaKnIwOqykfeeGX7sNQOaBOYlR1Lrg+mwgtXo0ig+5kkbkmtw1gvi
JPJItmIlkaAdpyAMDmMAojAYXnE6nIos9wx/7wWQalyVvVnV6lF80frPvA39XWn7
BVodD6i1F9mOdU3xi55TqVEPMOzdpJMA3XQnjoiXJJde5lVim7giWhVzE56y1Onu
Zg2Z/G4tC7ZulJXKRHKp2OxWwgrY5eBaoiP2Q3U1k1vZXi4Z1pWlM2EVApIZYKrk
y5Q6UbsGqQDKUSg3lq7y7pCvJlRTLgDF8cdOfQpodJhxoiM3SFrmqpaQjAsLgiOR
7lgdlkjRfxPZ787/7cRPE9cfa8QwPv9w+Rs8F4M/JbRDmxtikTg1kJIBLpDrWrln
Dm88HVATwP4JzuJ1HQHxXHtNLcjtZOOsXEwnGcBD/Q5fO42I6vmbumkynkMrSrNr
1g3ZQCr1zQPvf1i/xnDTvylnfyRwVAYQHpz1WCAnIQIDAQABMA0GCSqGSIb3DQEB
CwUAA4ICAQCYPmrm2DjB4BrAhER5XgJvhdiR7c6JditejpImObhrtRaZLsErQMEF
ypjrba1pfb5Yk+occpZh9r3sPN8G/vCooL1hZZ/WaPKybMzzkprXT3JSKIyOE7m0
G8asFv/mQQAkOfNK52QJTuqpDG/upXcwAguGO69yAC6RsmOjYEKMqXBIVJZJikQz
iSXa8lQZCMSIjDcOXOK+unETDkLdNWMVboBNnogQ8MyJW+3NDS0YDtr+428vZ/Vg
ixPx6lDkmdyyTLx8ebLHYI+A/Hu5DdO39SujxVdb5U2T/wvuFBRA1t5dDWyb41lG
Xi/HBCxojYTr7IYBnED7X4RtC5g2HZXKgh76M+0DZdWK3U3st18mP5Z5JN6MSgp4
iD0iixQQZl3pOQBmjMSuQOzouB2QmCAEn0S373hoCG5nijQU7GJhHizKiuo00YG5
3n0JAWq6/k07aYxJdP1D+unMsIW5QPTYWnQ/SQwSPWdTIkwov5vdtbPd6rtLY6rY
H4CceRQ2UYwfEjtWawVaq23WGGsv1/DApwtUr1+hQewNGWynVwkBiO5//N0q9EqL
K7su3MbjDeaSdzyPbLKsEhPZvKCyoYZ/HjF38Zwe6kOb5f/ghPAkRossREURQyqr
vRAj0swDekeWXxCrIucoS3031UY5pgNBeEUwENZ15w8+ZoS0HjB7Rw==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions cert/key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
pNup6c6DNzJiw9HN1eEUFBNtiVVIRrI=
-----END PRIVATE KEY-----
50 changes: 47 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//go:generate go-bindata openapi/openapi/fixtures3.json openapi/openapi/spec3.json
//go:generate go-bindata cert/cert.pem cert/key.pem openapi/openapi/fixtures3.json openapi/openapi/spec3.json

package main

import (
"crypto/tls"
"encoding/json"
"flag"
"fmt"
Expand All @@ -29,12 +30,14 @@ var version = "master"
// ---

func main() {
var https bool
var showVersion bool
var port int
var fixturesPath string
var specPath string
var unix string

flag.BoolVar(&https, "https", false, "Run with HTTPS (which also allows HTTP/2 to be activated)")
flag.IntVar(&port, "port", 0, "Port to listen on (also respects PORT from environment)")
flag.StringVar(&fixturesPath, "fixtures", "", "Path to fixtures to use instead of bundled version")
flag.StringVar(&specPath, "spec", "", "Path to OpenAPI spec to use instead of bundled version")
Expand Down Expand Up @@ -73,14 +76,39 @@ func main() {
}

http.HandleFunc("/", stub.HandleRequest)
server := http.Server{}

listener, err := getListener(port, unix)
if err != nil {
abort(err.Error())
}

server.Serve(listener)
if https {
// Our self-signed certificate is bundled up using go-bindata so that
// it stays easy to distribute stripe-mock as a standalone binary with
// no other dependencies.
certificate, err := getTLSCertificate()
if err != nil {
abort(err.Error())
}

tlsConfig := &tls.Config{
Certificates: []tls.Certificate{certificate},

// h2 is HTTP/2. A server with a default config normally doesn't
// need this hint, but Go is somewhat inflexible, and we need this
// here because we're using `Serve` and reading a TLS certificate
// from memory instead of using `ServeTLS` which would've read a
// certificate from file.
NextProtos: []string{"h2"},
}

server := http.Server{TLSConfig: tlsConfig}
tlsListener := tls.NewListener(listener, tlsConfig)
server.Serve(tlsListener)
} else {
server := http.Server{}
server.Serve(listener)
}
}

// ---
Expand All @@ -90,6 +118,22 @@ func abort(message string) {
os.Exit(1)
}

// getTLSCertificate reads a certificate and key from the assets built by
// go-bindata.
func getTLSCertificate() (tls.Certificate, error) {
cert, err := Asset("cert/cert.pem")
if err != nil {
return tls.Certificate{}, err
}

key, err := Asset("cert/key.pem")
if err != nil {
return tls.Certificate{}, err
}

return tls.X509KeyPair(cert, key)
}

// getEnvPortOrDefault gets a port from the environment variable `PORT` or
// falls back to the default port (`defaultPort`) if one was not present.
func getEnvPortOrDefault() (int, error) {
Expand Down

0 comments on commit bf95191

Please sign in to comment.