Skip to content

Instantly share code, notes, and snippets.

@liggitt
Last active August 26, 2018 19:42
Show Gist options
  • Save liggitt/00239c99b4c148ac1b23e57f86b3af93 to your computer and use it in GitHub Desktop.
Save liggitt/00239c99b4c148ac1b23e57f86b3af93 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"sync"
"time"
"golang.org/x/net/http2"
)
func main() {
client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
if err := http2.ConfigureTransport(client.Transport.(*http.Transport)); err != nil {
panic(err)
}
cert, _ := tls.X509KeyPair(LocalhostCert, LocalhostKey)
server := &http.Server{
Addr: "0.0.0.0:8080",
TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Body != nil {
defer r.Body.Close()
}
switch r.URL.Path {
case "/1":
// fmt.Printf(" %s: %v\n", r.URL.Path, r.Header.Get("Content-Length"))
// make a loopback post request
post(client, "/2", bytes.NewBufferString("data"))
// make a loopback post request draining the incoming request's body
post(client, "/3", r.Body)
default:
// fmt.Printf(" %s: %v\n", r.URL.Path, r.Header.Get("Content-Length"))
data, _ := ioutil.ReadAll(r.Body)
_ = data
// fmt.Println(" length", len(data))
}
}),
}
http2Options := &http2.Server{
// MaxConcurrentStreams: 250, // made the default explicit so we can size our buffers
// MaxUploadBufferPerStream: 256 * 1024, // shrunk from default 1MB
// MaxReadFrameSize: 256 * 1024, // shrunk from default 1MB
// MaxUploadBufferPerConnection: 256 * 1024 * 250, // grown from default 1MB to handle concurrent streams
}
if err := http2.ConfigureServer(server, http2Options); err != nil {
panic(err)
}
go func() {
fmt.Println(server.ListenAndServeTLS("", ""))
}()
// let the server establish
time.Sleep(time.Second)
// make a 10MB data block
data := make([]byte, 10*1024*1024)
// repeatedly and concurrently post data to /1 using client
wg := &sync.WaitGroup{}
wg.Add(200)
for i := 0; i < 200; i++ {
go func(i int) {
fmt.Printf("attempt %d -->\n", i)
post(client, "/1", bytes.NewReader(data))
fmt.Printf("attempt %d <--\n", i)
wg.Done()
}(i)
}
wg.Wait()
// quit
server.Close()
}
func post(client *http.Client, path string, body io.Reader) error {
req, err := http.NewRequest("POST", "https://127.0.0.1:8080"+path, body)
if err != nil {
return err
}
resp, err := client.Do(req)
if err != nil {
return err
}
ioutil.ReadAll(resp.Body)
resp.Body.Close()
return nil
}
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
fblo6RBxUQ==
-----END CERTIFICATE-----`)
// LocalhostKey is the private key for localhostCert.
var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
-----END RSA PRIVATE KEY-----`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment