| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- package httpclient
- import (
- "crypto/tls"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "sync"
- "testing"
- "time"
- )
- var starter sync.Once
- var addr net.Addr
- func testHandler(w http.ResponseWriter, req *http.Request) {
- time.Sleep(200 * time.Millisecond)
- io.WriteString(w, "hello, world!\n")
- }
- func postHandler(w http.ResponseWriter, req *http.Request) {
- ioutil.ReadAll(req.Body)
- w.Header().Set("Content-Length", "2")
- io.WriteString(w, "OK")
- }
- func closeHandler(w http.ResponseWriter, req *http.Request) {
- hj, _ := w.(http.Hijacker)
- conn, bufrw, _ := hj.Hijack()
- defer conn.Close()
- bufrw.WriteString("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n")
- bufrw.Flush()
- }
- func redirectHandler(w http.ResponseWriter, req *http.Request) {
- ioutil.ReadAll(req.Body)
- http.Redirect(w, req, "/post", 302)
- }
- func redirect2Handler(w http.ResponseWriter, req *http.Request) {
- ioutil.ReadAll(req.Body)
- http.Redirect(w, req, "/redirect", 302)
- }
- func slowHandler(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(200)
- io.WriteString(w, "START\n")
- f := w.(http.Flusher)
- f.Flush()
- time.Sleep(200 * time.Millisecond)
- io.WriteString(w, "WORKING\n")
- f.Flush()
- time.Sleep(200 * time.Millisecond)
- io.WriteString(w, "DONE\n")
- return
- }
- func setupMockServer(t *testing.T) {
- http.HandleFunc("/test", testHandler)
- http.HandleFunc("/post", postHandler)
- http.HandleFunc("/redirect", redirectHandler)
- http.HandleFunc("/redirect2", redirect2Handler)
- http.HandleFunc("/close", closeHandler)
- http.HandleFunc("/slow", slowHandler)
- ln, err := net.Listen("tcp", ":0")
- if err != nil {
- t.Fatalf("failed to listen - %s", err.Error())
- }
- go func() {
- err = http.Serve(ln, nil)
- if err != nil {
- t.Fatalf("failed to start HTTP server - %s", err.Error())
- }
- }()
- addr = ln.Addr()
- }
- func TestHttpsConnection(t *testing.T) {
- transport := &Transport{
- ConnectTimeout: 1 * time.Second,
- RequestTimeout: 2 * time.Second,
- TLSClientConfig: &tls.Config{
- InsecureSkipVerify: true,
- },
- }
- defer transport.Close()
- client := &http.Client{Transport: transport}
- req, _ := http.NewRequest("GET", "https://httpbin.org/ip", nil)
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("1st request failed - %s", err.Error())
- }
- _, err = ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatalf("1st failed to read body - %s", err.Error())
- }
- resp.Body.Close()
- req2, _ := http.NewRequest("GET", "https://httpbin.org/delay/5", nil)
- _, err = client.Do(req2)
- if err == nil {
- t.Fatalf("HTTPS request should have timed out")
- }
- }
- func TestHttpClient(t *testing.T) {
- starter.Do(func() { setupMockServer(t) })
- transport := &Transport{
- ConnectTimeout: 1 * time.Second,
- RequestTimeout: 5 * time.Second,
- ReadWriteTimeout: 3 * time.Second,
- }
- client := &http.Client{Transport: transport}
- req, _ := http.NewRequest("GET", "http://"+addr.String()+"/test", nil)
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("1st request failed - %s", err.Error())
- }
- _, err = ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatalf("1st failed to read body - %s", err.Error())
- }
- resp.Body.Close()
- transport.Close()
- transport = &Transport{
- ConnectTimeout: 25 * time.Millisecond,
- RequestTimeout: 50 * time.Millisecond,
- ReadWriteTimeout: 50 * time.Millisecond,
- }
- client = &http.Client{Transport: transport}
- req2, _ := http.NewRequest("GET", "http://"+addr.String()+"/test", nil)
- resp, err = client.Do(req2)
- if err == nil {
- t.Fatal("2nd request should have timed out")
- }
- transport.Close()
- transport = &Transport{
- ConnectTimeout: 25 * time.Millisecond,
- RequestTimeout: 250 * time.Millisecond,
- ReadWriteTimeout: 250 * time.Millisecond,
- }
- client = &http.Client{Transport: transport}
- req3, _ := http.NewRequest("GET", "http://"+addr.String()+"/test", nil)
- resp, err = client.Do(req3)
- if err != nil {
- t.Fatal("3rd request should not have timed out")
- }
- resp.Body.Close()
- transport.Close()
- }
- func TestSlowServer(t *testing.T) {
- starter.Do(func() { setupMockServer(t) })
- transport := &Transport{
- ConnectTimeout: 25 * time.Millisecond,
- RequestTimeout: 500 * time.Millisecond,
- ReadWriteTimeout: 250 * time.Millisecond,
- }
- client := &http.Client{Transport: transport}
- req, _ := http.NewRequest("GET", "http://"+addr.String()+"/slow", nil)
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("1st request failed - %s", err)
- }
- _, err = ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatalf("1st failed to read body - %s", err)
- }
- resp.Body.Close()
- transport.Close()
- transport = &Transport{
- ConnectTimeout: 25 * time.Millisecond,
- RequestTimeout: 500 * time.Millisecond,
- ReadWriteTimeout: 100 * time.Millisecond,
- }
- client = &http.Client{Transport: transport}
- req, _ = http.NewRequest("GET", "http://"+addr.String()+"/slow", nil)
- resp, err = client.Do(req)
- if err != nil {
- t.Fatalf("2nd request failed - %s", err)
- }
- _, err = ioutil.ReadAll(resp.Body)
- netErr, ok := err.(net.Error)
- if !ok {
- t.Fatalf("2nd request dind't return a net.Error - %s", netErr)
- }
- if !netErr.Timeout() {
- t.Fatalf("2nd request should have timed out - %s", netErr)
- }
- resp.Body.Close()
- transport.Close()
- }
- func TestMultipleRequests(t *testing.T) {
- starter.Do(func() { setupMockServer(t) })
- transport := &Transport{
- ConnectTimeout: 1 * time.Second,
- RequestTimeout: 5 * time.Second,
- ReadWriteTimeout: 3 * time.Second,
- ResponseHeaderTimeout: 400 * time.Millisecond,
- }
- client := &http.Client{Transport: transport}
- req, _ := http.NewRequest("GET", "http://"+addr.String()+"/test", nil)
- for i := 0; i < 10; i++ {
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("%d request failed - %s", i, err.Error())
- }
- _, err = ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatalf("%d failed to read body - %s", i, err.Error())
- }
- resp.Body.Close()
- }
- transport.Close()
- }
|