forked from yandex/pandora
-
Notifications
You must be signed in to change notification settings - Fork 0
/
http.go
108 lines (93 loc) · 2.58 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright (c) 2017 Yandex LLC. All rights reserved.
// Use of this source code is governed by a MPL 2.0
// license that can be found in the LICENSE file.
// Author: Vladimir Skipor <skipor@yandex-team.ru>
package phttp
import (
"net/http"
"github.com/pkg/errors"
)
type ClientGunConfig struct {
Target string `validate:"endpoint,required"`
SSL bool
Base BaseGunConfig `config:",squash"`
}
type HTTPGunConfig struct {
Gun ClientGunConfig `config:",squash"`
Client ClientConfig `config:",squash"`
}
type HTTP2GunConfig struct {
Gun ClientGunConfig `config:",squash"`
Client ClientConfig `config:",squash"`
}
func NewHTTPGun(conf HTTPGunConfig) *HTTPGun {
transport := NewTransport(conf.Client.Transport, NewDialer(conf.Client.Dialer).DialContext)
client := newClient(transport, conf.Client.Redirect)
return NewClientGun(client, conf.Gun)
}
// NewHTTP2Gun return simple HTTP/2 gun that can shoot sequentially through one connection.
func NewHTTP2Gun(conf HTTP2GunConfig) (*HTTPGun, error) {
if !conf.Gun.SSL {
// Open issue on github if you really need this feature.
return nil, errors.New("HTTP/2.0 over TCP is not supported. Please leave SSL option true by default.")
}
transport := NewHTTP2Transport(conf.Client.Transport, NewDialer(conf.Client.Dialer).DialContext)
client := newClient(transport, conf.Client.Redirect)
// Will panic and cancel shooting whet target doesn't support HTTP/2.
client = &panicOnHTTP1Client{client}
return NewClientGun(client, conf.Gun), nil
}
func NewClientGun(client Client, conf ClientGunConfig) *HTTPGun {
scheme := "http"
if conf.SSL {
scheme = "https"
}
var g HTTPGun
g = HTTPGun{
BaseGun: BaseGun{
Config: conf.Base,
Do: g.Do,
OnClose: func() error {
client.CloseIdleConnections()
return nil
},
},
scheme: scheme,
target: conf.Target,
client: client,
}
return &g
}
type HTTPGun struct {
BaseGun
scheme string
target string
client Client
}
var _ Gun = (*HTTPGun)(nil)
func (g *HTTPGun) Do(req *http.Request) (*http.Response, error) {
req.Host = req.URL.Host
req.URL.Host = g.target
req.URL.Scheme = g.scheme
return g.client.Do(req)
}
func NewDefaultHTTPGunConfig() HTTPGunConfig {
return HTTPGunConfig{
Gun: NewDefaultClientGunConfig(),
Client: NewDefaultClientConfig(),
}
}
func NewDefaultHTTP2GunConfig() HTTP2GunConfig {
conf := HTTP2GunConfig{
Client: NewDefaultClientConfig(),
Gun: NewDefaultClientGunConfig(),
}
conf.Gun.SSL = true
return conf
}
func NewDefaultClientGunConfig() ClientGunConfig {
return ClientGunConfig{
SSL: false,
Base: NewDefaultBaseGunConfig(),
}
}