-
Notifications
You must be signed in to change notification settings - Fork 34
/
fastcgi.go
171 lines (149 loc) · 4.42 KB
/
fastcgi.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package teaconfigs
import (
"errors"
"github.com/TeaWeb/code/teaconfigs/shared"
"github.com/TeaWeb/code/teaconst"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/utils/string"
"net/http"
"path/filepath"
"regexp"
"time"
)
// Fastcgi配置
type FastcgiConfig struct {
shared.HeaderList `yaml:",inline"`
On bool `yaml:"on" json:"on"`
Id string `yaml:"id" json:"id"`
// fastcgi地址配置
// 支持unix:/tmp/php-fpm.sock ...
Pass string `yaml:"pass" json:"pass"`
Index string `yaml:"index" json:"index"` //@TODO
Params map[string]string `yaml:"params" json:"params"` //@TODO
ReadTimeout string `yaml:"readTimeout" json:"readTimeout"` // @TODO 读取超时时间
SendTimeout string `yaml:"sendTimeout" json:"sendTimeout"` // @TODO 发送超时时间
ConnTimeout string `yaml:"connTimeout" json:"connTimeout"` // @TODO 连接超时时间
PoolSize int `yaml:"poolSize" json:"poolSize"` // 连接池尺寸
PathInfoPattern string `yaml:"pathInfoPattern" json:"pathInfoPattern"` // PATH_INFO匹配正则
network string // 协议:tcp, unix
address string // 地址
paramsMap maps.Map
readTimeout time.Duration
pathInfoRegexp *regexp.Regexp
}
// 获取新对象
func NewFastcgiConfig() *FastcgiConfig {
return &FastcgiConfig{
On: true,
Id: stringutil.Rand(16),
}
}
// 校验配置
func (this *FastcgiConfig) Validate() error {
this.paramsMap = maps.NewMap(this.Params)
if !this.paramsMap.Has("SCRIPT_FILENAME") {
this.paramsMap["SCRIPT_FILENAME"] = ""
}
if !this.paramsMap.Has("SERVER_SOFTWARE") {
this.paramsMap["SERVER_SOFTWARE"] = "teaweb/" + teaconst.TeaVersion
}
if !this.paramsMap.Has("REDIRECT_STATUS") {
this.paramsMap["REDIRECT_STATUS"] = "200"
}
if !this.paramsMap.Has("GATEWAY_INTERFACE") {
this.paramsMap["GATEWAY_INTERFACE"] = "CGI/1.1"
}
// 校验地址
if regexp.MustCompile("^\\d+$").MatchString(this.Pass) {
this.network = "tcp"
this.address = "127.0.0.1:" + this.Pass
} else if regexp.MustCompile("^(.*):(\\d+)$").MatchString(this.Pass) {
matches := regexp.MustCompile("^(.*):(\\d+)$").FindStringSubmatch(this.Pass)
ip := matches[1]
port := matches[2]
if len(ip) == 0 {
ip = "127.0.0.1"
}
this.network = "tcp"
this.address = ip + ":" + port
} else if regexp.MustCompile("^\\d+\\.\\d+.\\d+.\\d+$").MatchString(this.Pass) {
this.network = "tcp"
this.address = this.Pass + ":9000"
} else if regexp.MustCompile("^unix:(.+)$").MatchString(this.Pass) {
matches := regexp.MustCompile("^unix:(.+)$").FindStringSubmatch(this.Pass)
path := matches[1]
this.network = "unix"
this.address = path
} else if regexp.MustCompile("^[./].+$").MatchString(this.Pass) {
this.network = "unix"
this.address = this.Pass
} else {
return errors.New("invalid 'pass' format")
}
// 超时时间
if len(this.ReadTimeout) > 0 {
duration, err := time.ParseDuration(this.ReadTimeout)
if err != nil {
return err
}
this.readTimeout = duration
} else {
this.readTimeout = 3 * time.Second
}
// 校验Header
err := this.ValidateHeaders()
if err != nil {
return err
}
// PATH_INFO
if len(this.PathInfoPattern) > 0 {
reg, err := regexp.Compile(this.PathInfoPattern)
if err != nil {
return err
}
this.pathInfoRegexp = reg
}
return nil
}
// 过滤参数
func (this *FastcgiConfig) FilterParams(req *http.Request) maps.Map {
params := maps.NewMap(this.paramsMap)
// 自动添加参数
script := params.GetString("SCRIPT_FILENAME")
if len(script) > 0 {
if !params.Has("SCRIPT_NAME") {
params["SCRIPT_NAME"] = filepath.Base(script)
}
if !params.Has("DOCUMENT_ROOT") {
params["DOCUMENT_ROOT"] = filepath.Dir(script)
}
if !params.Has("PWD") {
params["PWD"] = filepath.Dir(script)
}
}
return params
}
// 超时时间
func (this *FastcgiConfig) ReadTimeoutDuration() time.Duration {
if this.readTimeout <= 0 {
this.readTimeout = 30 * time.Second
}
return this.readTimeout
}
//网络协议
func (this *FastcgiConfig) Network() string {
return this.network
}
// 网络地址
func (this *FastcgiConfig) Address() string {
return this.address
}
// 读取参数
func (this *FastcgiConfig) Param(paramName string) string {
v, _ := this.Params[paramName]
return v
}
// PATH_INFO正则
func (this *FastcgiConfig) PathInfoRegexp() *regexp.Regexp {
return this.pathInfoRegexp
}