阶段性提交
This commit is contained in:
@@ -7,5 +7,5 @@ type HealthCheckConfig struct {
|
||||
URL string `yaml:"url" json:"url"` // TODO
|
||||
Interval int `yaml:"interval" json:"interval"` // TODO
|
||||
StatusCodes []int `yaml:"statusCodes" json:"statusCodes"` // TODO
|
||||
Timeout shared.TimeDuration `yaml:"timeout" json:"timeout"` // 超时时间 TODO
|
||||
Timeout *shared.TimeDuration `yaml:"timeout" json:"timeout"` // 超时时间 TODO
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ import (
|
||||
var DefaultSkippedResponseCacheControlValues = []string{"private", "no-cache", "no-store"}
|
||||
|
||||
// 缓存策略配置
|
||||
type CachePolicy struct {
|
||||
type HTTPCachePolicy struct {
|
||||
Id int `yaml:"id" json:"id"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启 TODO
|
||||
Name string `yaml:"name" json:"name"` // 名称
|
||||
|
||||
Key string `yaml:"key" json:"key"` // 每个缓存的Key规则,里面可以有变量
|
||||
Capacity shared.SizeCapacity `yaml:"capacity" json:"capacity"` // 最大内容容量
|
||||
Life shared.TimeDuration `yaml:"life" json:"life"` // 时间
|
||||
Capacity *shared.SizeCapacity `yaml:"capacity" json:"capacity"` // 最大内容容量
|
||||
Life *shared.TimeDuration `yaml:"life" json:"life"` // 时间
|
||||
Status []int `yaml:"status" json:"status"` // 缓存的状态码列表
|
||||
MaxSize shared.SizeCapacity `yaml:"maxSize" json:"maxSize"` // 能够请求的最大尺寸
|
||||
MaxSize *shared.SizeCapacity `yaml:"maxSize" json:"maxSize"` // 能够请求的最大尺寸
|
||||
|
||||
SkipResponseCacheControlValues []string `yaml:"skipCacheControlValues" json:"skipCacheControlValues"` // 可以跳过的响应的Cache-Control值
|
||||
SkipResponseSetCookie bool `yaml:"skipSetCookie" json:"skipSetCookie"` // 是否跳过响应的Set-Cookie Header
|
||||
@@ -43,15 +43,15 @@ type CachePolicy struct {
|
||||
}
|
||||
|
||||
// 获取新对象
|
||||
func NewCachePolicy() *CachePolicy {
|
||||
return &CachePolicy{
|
||||
func NewHTTPCachePolicy() *HTTPCachePolicy {
|
||||
return &HTTPCachePolicy{
|
||||
SkipResponseCacheControlValues: DefaultSkippedResponseCacheControlValues,
|
||||
SkipResponseSetCookie: true,
|
||||
}
|
||||
}
|
||||
|
||||
// 从文件中读取缓存策略
|
||||
func NewCachePolicyFromFile(file string) *CachePolicy {
|
||||
func NewCachePolicyFromFile(file string) *HTTPCachePolicy {
|
||||
if len(file) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func NewCachePolicyFromFile(file string) *CachePolicy {
|
||||
_ = reader.Close()
|
||||
}()
|
||||
|
||||
p := NewCachePolicy()
|
||||
p := NewHTTPCachePolicy()
|
||||
err = reader.ReadYAML(p)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
@@ -75,7 +75,7 @@ func NewCachePolicyFromFile(file string) *CachePolicy {
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *CachePolicy) Validate() error {
|
||||
func (this *HTTPCachePolicy) Validate() error {
|
||||
var err error
|
||||
this.maxSize = this.MaxSize.Bytes()
|
||||
this.life = this.Life.Duration()
|
||||
@@ -100,22 +100,22 @@ func (this *CachePolicy) Validate() error {
|
||||
}
|
||||
|
||||
// 最大数据尺寸
|
||||
func (this *CachePolicy) MaxDataSize() int64 {
|
||||
func (this *HTTPCachePolicy) MaxDataSize() int64 {
|
||||
return this.maxSize
|
||||
}
|
||||
|
||||
// 容量
|
||||
func (this *CachePolicy) CapacitySize() int64 {
|
||||
func (this *HTTPCachePolicy) CapacitySize() int64 {
|
||||
return this.capacity
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
func (this *CachePolicy) LifeDuration() time.Duration {
|
||||
func (this *HTTPCachePolicy) LifeDuration() time.Duration {
|
||||
return this.life
|
||||
}
|
||||
|
||||
// 保存
|
||||
func (this *CachePolicy) Save() error {
|
||||
func (this *HTTPCachePolicy) Save() error {
|
||||
shared.Locker.Lock()
|
||||
defer shared.Locker.Unlock()
|
||||
|
||||
@@ -132,18 +132,18 @@ func (this *CachePolicy) Save() error {
|
||||
}
|
||||
|
||||
// 删除
|
||||
func (this *CachePolicy) Delete() error {
|
||||
func (this *HTTPCachePolicy) Delete() error {
|
||||
filename := "cache.policy." + strconv.Itoa(this.Id) + ".conf"
|
||||
return files.NewFile(Tea.ConfigFile(filename)).Delete()
|
||||
}
|
||||
|
||||
// 是否包含某个Cache-Control值
|
||||
func (this *CachePolicy) ContainsCacheControl(value string) bool {
|
||||
func (this *HTTPCachePolicy) ContainsCacheControl(value string) bool {
|
||||
return lists.ContainsString(this.uppercaseSkipCacheControlValues, strings.ToUpper(value))
|
||||
}
|
||||
|
||||
// 检查是否匹配关键词
|
||||
func (this *CachePolicy) MatchKeyword(keyword string) (matched bool, name string, tags []string) {
|
||||
func (this *HTTPCachePolicy) MatchKeyword(keyword string) (matched bool, name string, tags []string) {
|
||||
if configutils.MatchKeyword(this.Name, keyword) || configutils.MatchKeyword(this.Type, keyword) {
|
||||
matched = true
|
||||
name = this.Name
|
||||
79
pkg/serverconfigs/http_gzip_config.go
Normal file
79
pkg/serverconfigs/http_gzip_config.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 默认的文件类型
|
||||
var (
|
||||
DefaultGzipMimeTypes = []string{"text/html", "application/json"}
|
||||
)
|
||||
|
||||
// gzip配置
|
||||
type HTTPGzipConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Level int8 `yaml:"level" json:"level"` // 1-9
|
||||
MinLength *shared.SizeCapacity `yaml:"minLength" json:"minLength"` // 最小压缩对象比如4m, 24k
|
||||
MaxLength *shared.SizeCapacity `yaml:"minLength" json:"maxLength"` // 最大压缩对象 TODO 需要实现
|
||||
MimeTypes []string `yaml:"mimeTypes" json:"mimeTypes"` // 比如text/html, text/* // TODO 需要实现,可能需要用RequestConds替代
|
||||
|
||||
minLength int64
|
||||
mimeTypes []*MimeTypeRule
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPGzipConfig) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
|
||||
if len(this.MimeTypes) == 0 {
|
||||
this.MimeTypes = DefaultGzipMimeTypes
|
||||
}
|
||||
|
||||
this.mimeTypes = []*MimeTypeRule{}
|
||||
for _, mimeType := range this.MimeTypes {
|
||||
if strings.Contains(mimeType, "*") {
|
||||
mimeType = regexp.QuoteMeta(mimeType)
|
||||
mimeType = strings.Replace(mimeType, "\\*", ".*", -1)
|
||||
reg, err := regexp.Compile("^" + mimeType + "$")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.mimeTypes = append(this.mimeTypes, &MimeTypeRule{
|
||||
Value: mimeType,
|
||||
Regexp: reg,
|
||||
})
|
||||
} else {
|
||||
this.mimeTypes = append(this.mimeTypes, &MimeTypeRule{
|
||||
Value: mimeType,
|
||||
Regexp: nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 可压缩最小尺寸
|
||||
func (this *HTTPGzipConfig) MinBytes() int64 {
|
||||
return this.minLength
|
||||
}
|
||||
|
||||
// 检查是否匹配Content-Type
|
||||
func (this *HTTPGzipConfig) MatchContentType(contentType string) bool {
|
||||
index := strings.Index(contentType, ";")
|
||||
if index >= 0 {
|
||||
contentType = contentType[:index]
|
||||
}
|
||||
for _, mimeType := range this.mimeTypes {
|
||||
if mimeType.Regexp == nil && contentType == mimeType.Value {
|
||||
return true
|
||||
} else if mimeType.Regexp != nil && mimeType.Regexp.MatchString(contentType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
43
pkg/serverconfigs/http_gzip_config_test.go
Normal file
43
pkg/serverconfigs/http_gzip_config_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGzipConfig_MatchContentType(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
gzip := &HTTPGzipConfig{}
|
||||
a.IsNil(gzip.Init())
|
||||
a.IsTrue(gzip.MatchContentType("text/html"))
|
||||
}
|
||||
|
||||
{
|
||||
gzip := &HTTPGzipConfig{}
|
||||
a.IsNil(gzip.Init())
|
||||
a.IsTrue(gzip.MatchContentType("text/html; charset=utf-8"))
|
||||
}
|
||||
|
||||
{
|
||||
gzip := &HTTPGzipConfig{}
|
||||
gzip.MimeTypes = []string{"text/*"}
|
||||
a.IsNil(gzip.Init())
|
||||
a.IsTrue(gzip.MatchContentType("text/html; charset=utf-8"))
|
||||
}
|
||||
|
||||
{
|
||||
gzip := &HTTPGzipConfig{}
|
||||
gzip.MimeTypes = []string{"text/*"}
|
||||
a.IsNil(gzip.Init())
|
||||
a.IsFalse(gzip.MatchContentType("application/json; charset=utf-8"))
|
||||
}
|
||||
|
||||
{
|
||||
gzip := &HTTPGzipConfig{}
|
||||
gzip.MimeTypes = []string{"text/*", "image/*"}
|
||||
a.IsNil(gzip.Init())
|
||||
a.IsTrue(gzip.MatchContentType("image/jpeg; charset=utf-8"))
|
||||
}
|
||||
}
|
||||
11
pkg/serverconfigs/http_web_config.go
Normal file
11
pkg/serverconfigs/http_web_config.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package serverconfigs
|
||||
|
||||
type HTTPWebConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Locations []*LocationConfig `yaml:"locations" json:"locations"` // 路径规则 TODO
|
||||
Gzip *HTTPGzipConfig `yaml:"gzip" json:"gzip"` // Gzip配置
|
||||
|
||||
// 本地静态资源配置
|
||||
Root string `yaml:"root" json:"root"` // 资源根目录 TODO
|
||||
}
|
||||
9
pkg/serverconfigs/mime_type_rule.go
Normal file
9
pkg/serverconfigs/mime_type_rule.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package serverconfigs
|
||||
|
||||
import "regexp"
|
||||
|
||||
// mime type
|
||||
type MimeTypeRule struct {
|
||||
Value string
|
||||
Regexp *regexp.Regexp
|
||||
}
|
||||
@@ -22,13 +22,13 @@ type OriginServerConfig struct {
|
||||
Description string `yaml:"description" json:"description"` // 描述 TODO
|
||||
Code string `yaml:"code" json:"code"` // 代号 TODO
|
||||
|
||||
Weight uint `yaml:"weight" json:"weight"` // 权重 TODO
|
||||
ConnTimeout shared.TimeDuration `yaml:"failTimeout" json:"failTimeout"` // 连接失败超时 TODO
|
||||
ReadTimeout shared.TimeDuration `yaml:"readTimeout" json:"readTimeout"` // 读取超时时间 TODO
|
||||
IdleTimeout shared.TimeDuration `yaml:"idleTimeout" json:"idleTimeout"` // 空闲连接超时时间 TODO
|
||||
MaxFails int `yaml:"maxFails" json:"maxFails"` // 最多失败次数 TODO
|
||||
MaxConns int `yaml:"maxConns" json:"maxConns"` // 最大并发连接数 TODO
|
||||
MaxIdleConns int `yaml:"idleConns" json:"idleConns"` // 最大空闲连接数 TODO
|
||||
Weight uint `yaml:"weight" json:"weight"` // 权重 TODO
|
||||
ConnTimeout *shared.TimeDuration `yaml:"failTimeout" json:"failTimeout"` // 连接失败超时 TODO
|
||||
ReadTimeout *shared.TimeDuration `yaml:"readTimeout" json:"readTimeout"` // 读取超时时间 TODO
|
||||
IdleTimeout *shared.TimeDuration `yaml:"idleTimeout" json:"idleTimeout"` // 空闲连接超时时间 TODO
|
||||
MaxFails int `yaml:"maxFails" json:"maxFails"` // 最多失败次数 TODO
|
||||
MaxConns int `yaml:"maxConns" json:"maxConns"` // 最大并发连接数 TODO
|
||||
MaxIdleConns int `yaml:"idleConns" json:"idleConns"` // 最大空闲连接数 TODO
|
||||
|
||||
RequestURI string `yaml:"requestURI" json:"requestURI"` // 转发后的请求URI TODO
|
||||
Host string `yaml:"host" json:"host"` // 自定义主机名 TODO
|
||||
|
||||
@@ -25,7 +25,7 @@ type ServerConfig struct {
|
||||
UDP *UDPProtocolConfig `yaml:"udp" json:"udp"` // UDP配置
|
||||
|
||||
// Web配置
|
||||
Web *WebConfig `yaml:"web" json:"web"`
|
||||
Web *HTTPWebConfig `yaml:"web" json:"web"`
|
||||
|
||||
// 反向代理配置
|
||||
ReverseProxy *ReverseProxyConfig `yaml:"reverseProxy" json:"reverseProxy"`
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package shared
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type SizeCapacityUnit = string
|
||||
|
||||
const (
|
||||
@@ -28,3 +30,7 @@ func (this *SizeCapacity) Bytes() int64 {
|
||||
return this.Count
|
||||
}
|
||||
}
|
||||
|
||||
func (this *SizeCapacity) AsJSON() ([]byte, error) {
|
||||
return json.Marshal(this)
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
type WebConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
|
||||
Locations []*LocationConfig `yaml:"locations" json:"locations"` // 路径规则 TODO
|
||||
|
||||
// 本地静态资源配置
|
||||
Root string `yaml:"root" json:"root"` // 资源根目录 TODO
|
||||
}
|
||||
Reference in New Issue
Block a user