forked from TarsCloud/TarsGo
-
Notifications
You must be signed in to change notification settings - Fork 4
/
httpserver.go
136 lines (121 loc) · 3.01 KB
/
httpserver.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
package tars
import (
"fmt"
"net/http"
"strings"
"time"
"tars/protocol/res/statf"
)
var realIPHeader []string
func init() {
realIPHeader = []string{ // the order is important
"X-Real-Ip",
"X-Forwarded-For-Pound",
"X-Forwarded-For",
}
}
//TarsHttpConf is configuration for tars http server.
type TarsHttpConf struct {
Container string
AppName string
IP string
Port int32
Version string
SetId string
}
//TarsHttpMux is http.ServeMux for tars http server.
type TarsHttpMux struct {
http.ServeMux
cfg *TarsHttpConf
}
type httpStatInfo struct {
reqAddr string
pattern string
statusCode int
costTime int64
}
//ServeHTTP is the server for the TarsHttpMux.
func (mux *TarsHttpMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(http.StatusBadRequest)
return
}
h, pattern := mux.Handler(r)
tw := &TarsResponseWriter{w, 0}
startTime := time.Now().UnixNano() / 1000000
h.ServeHTTP(tw, r)
costTime := int64(time.Now().UnixNano()/1000000 - startTime)
var reqAddr string
for _, h := range realIPHeader {
reqAddr = r.Header.Get(h)
if reqAddr != "" {
break
}
}
if reqAddr == "" { // no proxy
reqAddr = strings.SplitN(r.RemoteAddr, ":", 2)[0]
}
if pattern == "" {
pattern = "/"
}
st := &httpStatInfo{
reqAddr: reqAddr,
pattern: pattern,
statusCode: tw.statusCode,
costTime: costTime,
}
go mux.reportHttpStat(st)
}
func (mux *TarsHttpMux) reportHttpStat(st *httpStatInfo) {
if mux.cfg == nil {
return
}
cfg := mux.cfg
var _statInfo = statf.StatMicMsgHead{}
_statInfo.MasterName = "http_client"
_statInfo.MasterIp = st.reqAddr
_statInfo.TarsVersion = cfg.Version
_statInfo.SlaveName = cfg.AppName
_statInfo.SlaveIp = cfg.IP // from server
_statInfo.SlavePort = cfg.Port
//_statInfo.SSlaveContainer = cfg.Container
_statInfo.InterfaceName = st.pattern
if cfg.SetId != "" {
setList := strings.Split(cfg.SetId, ".")
_statInfo.SlaveSetName = setList[0]
_statInfo.SlaveSetArea = setList[1]
_statInfo.SlaveSetID = setList[2]
//被调也要加上set信息
_statInfo.SlaveName = fmt.Sprintf("http_client.%s%s%s", setList[0], setList[1], setList[2])
}
var _statBody = statf.StatMicMsgBody{}
if st.statusCode >= 400 {
_statBody.ExecCount = 1 // 异常
} else {
_statBody.Count = 1
_statBody.TotalRspTime = st.costTime
_statBody.MaxRspTime = int32(st.costTime)
_statBody.MinRspTime = int32(st.costTime)
}
info := StatInfo{}
info.Head = _statInfo
info.Body = _statBody
StatReport.pushBackMsg(info, true)
}
//SetConfig sets the cfg tho the TarsHttpMux.
func (mux *TarsHttpMux) SetConfig(cfg *TarsHttpConf) {
mux.cfg = cfg
}
//TarsResponseWriter is http.ResponseWriter for tars.
type TarsResponseWriter struct {
http.ResponseWriter
statusCode int
}
//WriteHeader is used for write the http header with the http code.
func (w *TarsResponseWriter) WriteHeader(code int) {
w.statusCode = code
w.ResponseWriter.WriteHeader(code)
}