-
Notifications
You must be signed in to change notification settings - Fork 0
/
PluginHTTP.go
152 lines (143 loc) · 4.2 KB
/
PluginHTTP.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package vweb
import (
"net"
"net/http"
"crypto/tls"
"time"
"context"
"github.com/456vv/verror"
)
//http插件接口
type PluginHTTP interface{
Type() PluginType // 类型
ServeHTTP(w http.ResponseWriter, r *http.Request) // 服务HTTP
RoundTrip(r *http.Request) (resp *http.Response, err error) // 代理
CancelRequest(req *http.Request) // 取消HTTP请求
CloseIdleConnections() // 关闭空闲连接
RegisterProtocol(scheme string, rt http.RoundTripper) // 注册新协议
}
//插件HTTP客户端
type PluginHTTPClient struct{
Tr *http.Transport // 客户端
Addr string // 地址
Scheme string // 协议(用于默认填充)
Host string // 请求Host(用于默认填充)
Dialer *net.Dialer
}
//快速连接HTTP
// PluginHTTP 插件HTTP
// error 错误
func (T *PluginHTTPClient) Connection() (PluginHTTP, error) {
if T.Tr == nil {
return nil, verror.TrackError("vweb: Tr字段不可以为空!")
}
if T.Dialer == nil {
T.Dialer = &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}
}
if T.Addr != "" {
if T.Tr.DialContext == nil {
T.Tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error){
return T.Dialer.DialContext(ctx, network, T.Addr)
}
}
if T.Tr.TLSClientConfig != nil {
T.Tr.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error){
return tls.DialWithDialer(T.Dialer, network, T.Addr, T.Tr.TLSClientConfig)
}
}
}
return &pluginHTTP{tr:T.Tr, host:T.Host, scheme:T.Scheme}, nil
}
//pluginHTTP 连接HTTP
type pluginHTTP struct{
tr *http.Transport
host string
scheme string
}
//插件类型
// PluginType 插件类型
func (T *pluginHTTP) Type() PluginType {
return PluginTypeHTTP
}
//ServeHTTP 服务器处理
// w http.ResponseWriter 响应
// r *http.Request 请求
func (T *pluginHTTP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
resp, err := T.RoundTrip(r)
if err != nil {
//504错误是(网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
http.Error(w, err.Error(), http.StatusGatewayTimeout)
return
}
//写入header标头
rh := resp.Header
wh := w.Header()
for key, values := range rh {
for _, value := range values {
wh.Add(key, value)
}
}
//写入状态码
w.WriteHeader(resp.StatusCode)
//写入body数据
body := resp.Body
defer body.Close()
//io.Copy(rw, body)
p := make([]byte, defaultDataBufioSize)
flush := w.(http.Flusher)
for {
nr, er := body.Read(p)
if nr > 0 {
nw, ew := w.Write(p[:nr])
if ew != nil || nr != nw {
//日志
break
}
flush.Flush()
}
if er != nil {
//日志
break
}
}
}
//RoundTrip 单一的HTTP请求
// r *http.Request 请求
// resp *http.Response 响应
// err error 错误
func (T *pluginHTTP) RoundTrip(r *http.Request) (resp *http.Response, err error) {
//由于req中的URL不完整,需要补充
T.fillCompleteURL(r)
return T.tr.RoundTrip(r)
}
//fillCompleteURL 补充完整URL
// r *http.Request 请求
func (T *pluginHTTP) fillCompleteURL(r *http.Request) {
if r.Host == "" {
r.Host = T.host
r.Header.Set("Host", r.Host)
}
r.URL.Host = r.Host
if r.URL.Scheme == "" {
r.URL.Scheme = T.scheme
}
}
//CancelRequest 取消HTTP请求
// r *http.Request 请求
func (T *pluginHTTP) CancelRequest(r *http.Request) {
T.tr.CancelRequest(r)
}
//CloseIdleConnections 关闭空闲连接
func (T *pluginHTTP) CloseIdleConnections() {
T.tr.CloseIdleConnections()
}
//RegisterProtocol 注册新协议
// scheme string 协议
// rt http.RoundTripper 新代理
func (T *pluginHTTP) RegisterProtocol(scheme string, rt http.RoundTripper) {
T.tr.RegisterProtocol(scheme, rt)
}