github.com/useflyent/fhttp@v0.0.0-20211004035111-333f430cfbbf/http2/fhttp_test.go (about) 1 package http2_test 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "crypto/x509" 7 "errors" 8 "fmt" 9 "github.com/useflyent/fhttp/cookiejar" 10 "github.com/useflyent/fhttp/httptest" 11 "golang.org/x/net/publicsuffix" 12 "log" 13 ghttp "net/http" 14 "net/url" 15 "os" 16 "strings" 17 "testing" 18 19 http "github.com/useflyent/fhttp" 20 "github.com/useflyent/fhttp/http2" 21 ) 22 23 // Tests if connection settings are written correctly 24 func TestConnectionSettings(t *testing.T) { 25 settings := []http2.Setting{ 26 {ID: http2.SettingHeaderTableSize, Val: 65536}, 27 {ID: http2.SettingMaxConcurrentStreams, Val: 1000}, 28 {ID: http2.SettingInitialWindowSize, Val: 6291456}, 29 {ID: http2.SettingMaxFrameSize, Val: 16384}, 30 {ID: http2.SettingMaxHeaderListSize, Val: 262144}, 31 } 32 buf := new(bytes.Buffer) 33 fr := http2.NewFramer(buf, buf) 34 err := fr.WriteSettings(settings...) 35 36 if err != nil { 37 t.Fatalf(err.Error()) 38 } 39 40 f, err := fr.ReadFrame() 41 if err != nil { 42 t.Fatal(err.Error()) 43 } 44 45 sf := f.(*http2.SettingsFrame) 46 n := sf.NumSettings() 47 if n != len(settings) { 48 t.Fatalf("Expected %d settings, got %d", len(settings), n) 49 } 50 51 for i := 0; i < n; i++ { 52 s := sf.Setting(i) 53 var err error 54 switch s.ID { 55 case http2.SettingHeaderTableSize: 56 err = compareSettings(s.ID, s.Val, 65536) 57 case http2.SettingMaxConcurrentStreams: 58 err = compareSettings(s.ID, s.Val, 1000) 59 case http2.SettingInitialWindowSize: 60 err = compareSettings(s.ID, s.Val, 6291456) 61 case http2.SettingMaxFrameSize: 62 err = compareSettings(s.ID, s.Val, 16384) 63 case http2.SettingMaxHeaderListSize: 64 err = compareSettings(s.ID, s.Val, 262144) 65 } 66 67 if err != nil { 68 t.Fatal(err.Error()) 69 } 70 } 71 } 72 73 func compareSettings(ID http2.SettingID, output uint32, expected uint32) error { 74 if output != expected { 75 return errors.New(fmt.Sprintf("Setting %v, expected %d got %d", ID, expected, output)) 76 } 77 return nil 78 } 79 80 // Round trip test, makes sure that the changes made doesn't break the library 81 func TestRoundTrip(t *testing.T) { 82 settings := []http2.Setting{ 83 {ID: http2.SettingHeaderTableSize, Val: 65536}, 84 {ID: http2.SettingMaxConcurrentStreams, Val: 1000}, 85 {ID: http2.SettingInitialWindowSize, Val: 6291456}, 86 {ID: http2.SettingMaxFrameSize, Val: 16384}, 87 {ID: http2.SettingMaxHeaderListSize, Val: 262144}, 88 } 89 tr := http2.Transport{ 90 Settings: settings, 91 } 92 req, err := http.NewRequest("GET", "www.google.com", nil) 93 if err != nil { 94 t.Fatalf(err.Error()) 95 } 96 tr.RoundTrip(req) 97 } 98 99 // Tests if content-length header is present in request headers during POST 100 func TestContentLength(t *testing.T) { 101 ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 102 if hdr, ok := r.Header["Content-Length"]; ok { 103 if len(hdr) != 1 { 104 t.Fatalf("Got %v content-length headers, should only be 1", len(hdr)) 105 } 106 return 107 } 108 log.Printf("Proto: %v", r.Proto) 109 for name, value := range r.Header { 110 log.Printf("%v: %v", name, value) 111 } 112 t.Fatalf("Could not find content-length header") 113 })) 114 ts.EnableHTTP2 = true 115 ts.StartTLS() 116 defer ts.Close() 117 118 u := ts.URL 119 form := url.Values{} 120 form.Add("Hello", "World") 121 req, err := http.NewRequest("POST", u, strings.NewReader(form.Encode())) 122 if err != nil { 123 t.Fatalf(err.Error()) 124 } 125 req.Header.Add("user-agent", "Go Testing") 126 127 resp, err := ts.Client().Do(req) 128 if err != nil { 129 t.Fatalf(err.Error()) 130 } 131 defer resp.Body.Close() 132 } 133 134 // TestClient_Cookies tests whether set cookies are being sent 135 func TestClient_SendsCookies(t *testing.T) { 136 ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 137 cookie, err := r.Cookie("cookie") 138 if err != nil { 139 t.Fatalf(err.Error()) 140 } 141 if cookie.Value == "" { 142 t.Fatalf("Cookie value is empty") 143 } 144 })) 145 ts.EnableHTTP2 = true 146 ts.StartTLS() 147 defer ts.Close() 148 c := ts.Client() 149 jar, err := cookiejar.New(&cookiejar.Options{ 150 PublicSuffixList: publicsuffix.List, 151 }) 152 if err != nil { 153 t.Fatalf(err.Error()) 154 } 155 c.Jar = jar 156 ur := ts.URL 157 u, err := url.Parse(ur) 158 if err != nil { 159 t.Fatalf(err.Error()) 160 } 161 cookies := []*http.Cookie{{Name: "cookie", Value: "Hello world"}} 162 jar.SetCookies(u, cookies) 163 resp, err := c.Get(ur) 164 if err != nil { 165 t.Fatalf(err.Error()) 166 } 167 defer resp.Body.Close() 168 } 169 170 // TestClient_Load is a dumb man's load test with charles :P 171 func TestClient_Load(t *testing.T) { 172 u, err := url.Parse("http://localhost:8888") 173 if err != nil { 174 t.Fatalf(err.Error()) 175 } 176 177 pool, err := getCharlesCert() 178 if err != nil { 179 t.Fatalf(err.Error()) 180 } 181 c := http.Client{ 182 Transport: &http.Transport{ 183 ForceAttemptHTTP2: true, 184 Proxy: http.ProxyURL(u), 185 TLSClientConfig: &tls.Config{ 186 RootCAs: pool, 187 }, 188 }, 189 } 190 req, err := http.NewRequest("GET", "https://golang.org/pkg/net/mail/#Address", nil) 191 if err != nil { 192 t.Fatalf(err.Error()) 193 } 194 for i := 0; i < 10; i++ { 195 resp, err := c.Do(req) 196 if err != nil { 197 t.Fatalf(err.Error()) 198 } 199 resp.Body.Close() 200 } 201 } 202 203 func TestGClient_Load(t *testing.T) { 204 u, err := url.Parse("http://localhost:8888") 205 if err != nil { 206 t.Fatalf(err.Error()) 207 } 208 209 pool, err := getCharlesCert() 210 if err != nil { 211 t.Fatalf(err.Error()) 212 } 213 c := ghttp.Client{ 214 Transport: &ghttp.Transport{ 215 ForceAttemptHTTP2: true, 216 Proxy: ghttp.ProxyURL(u), 217 TLSClientConfig: &tls.Config{ 218 RootCAs: pool, 219 }, 220 }, 221 } 222 req, err := ghttp.NewRequest("GET", "https://golang.org/pkg/net/mail/#Address", nil) 223 if err != nil { 224 t.Fatalf(err.Error()) 225 } 226 for i := 0; i < 10; i++ { 227 err := do(&c, req) 228 if err != nil { 229 t.Fatalf(err.Error()) 230 } 231 } 232 } 233 234 func do(c *ghttp.Client, req *ghttp.Request) error { 235 resp, err := c.Do(req) 236 if err != nil { 237 return err 238 } 239 resp.Body.Close() 240 return nil 241 } 242 243 func getCharlesCert() (*x509.CertPool, error) { 244 home, err := os.UserHomeDir() 245 if err != nil { 246 return nil, err 247 } 248 caCert, err := os.ReadFile(fmt.Sprintf("%v/charles_cert.pem", home)) 249 if err != nil { 250 return nil, err 251 } 252 certPool := x509.NewCertPool() 253 certPool.AppendCertsFromPEM(caCert) 254 return certPool, nil 255 }