Skip to content

Instantly share code, notes, and snippets.

@odeke-em
Last active August 31, 2017 08:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odeke-em/876d24325d16b3885388f7f0dae9611d to your computer and use it in GitHub Desktop.
Save odeke-em/876d24325d16b3885388f7f0dae9611d to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"fmt"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"time"
)
func main() {
var theURL string
flag.StringVar(&theURL, "url", "http://localhost:8877", "the server address")
flag.Parse()
proxyURL, _ := url.Parse(theURL)
client := &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 5 * time.Second,
DisableKeepAlives: true,
},
}
r, _ := http.NewRequest("POST", "https://golang.org/", nil)
res, err := client.Do(r)
if err != nil {
log.Fatalf("res: %v", err)
}
wire, err := httputil.DumpResponse(res, true)
if err != nil {
log.Fatal(err)
}
fmt.Printf("wire: %s\n", wire)
}
package main
import (
"flag"
"fmt"
"log"
"net"
)
func main() {
var port int
flag.IntVar(&port, "port", 8877, "the port to listen on")
flag.Parse()
addr := fmt.Sprintf(":%d", port)
log.Printf("server listening at %q\n", addr)
ln, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal("listen: %v", err)
}
for {
conn, err := ln.Accept()
if err != nil {
log.Printf("listen err: %v", err)
continue
}
go handleConn(conn)
}
}
var malformed = []byte(
`HTTP/1.1 400
Date: Wed, 30 Aug 2017 19:09:27 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 10
Connection: close
Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT
Vary: Accept-Encoding
Server: cloudflare-nginx` + "\r\n\r\nAloha Olaa")
func handleConn(conn net.Conn) {
conn.Write(malformed)
conn.Close()
}
// Ensure that a missing status doesn't make the server panic
// See Issue https://golang.org/issues/21701
func TestMissingStatusNoPanic(t *testing.T) {
t.Parallel()
ln := newLocalListener(t)
addr := ln.Addr().String()
rawRespChan := make(chan string, 1)
shutdown := make(chan bool, 1)
done := make(chan bool)
fullAddrURL := fmt.Sprintf("http://%s", addr)
go func() {
defer func() {
ln.Close()
close(done)
}()
running := true
for running {
select {
case <-shutdown:
running = false
case rawResp := <-rawRespChan:
conn, _ := ln.Accept()
if conn != nil {
io.WriteString(conn, rawResp)
conn.Close()
}
}
}
}()
tests := [...]struct {
raw string
want string
}{
0: {
want: "unknown status code",
raw: `HTTP/1.1 400
Date: Wed, 30 Aug 2017 19:09:27 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 10
Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT
Vary: Accept-Encoding` + "\r\n\r\nAloha Olaa",
},
1: {
want: "malformed HTTP",
raw: `HTTP/1.1
Date: Wed, 30 Aug 2017 19:09:27 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 10
Last-Modified: Wed, 30 Aug 2017 19:02:02 GMT
Vary: Accept-Encoding` + "\r\n\r\nAloha Olaa",
},
}
proxyURL, err := url.Parse(fullAddrURL)
if err != nil {
t.Fatalf("proxyURL: %v", err)
}
client := &Client{
Transport: &Transport{Proxy: ProxyURL(proxyURL)},
}
for i, tt := range tests {
rawRespChan <- tt.raw
req, _ := NewRequest("POST", "https://golang.org/", nil)
res, err, panicked := doFetchCheckPanic(client, req)
if panicked {
t.Errorf("#%d: panicked, expecting an error", i)
continue
}
if res != nil && res.Body != nil {
io.Copy(ioutil.Discard, res.Body)
res.Body.Close()
}
if err == nil || !strings.Contains(err.Error(), tt.want) {
t.Errorf("#%d: got=%v want=%q", i, err, tt.want)
}
}
close(shutdown)
<-done
}
func doFetchCheckPanic(c *Client, req *Request) (res *Response, err error, panicked bool) {
defer func() {
if r := recover(); r != nil {
panicked = true
}
}()
res, err = c.Do(req)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment