阶段性提交

This commit is contained in:
GoEdgeLab
2020-09-16 09:09:31 +08:00
parent aa86446f4f
commit 1648192e73
24 changed files with 2156 additions and 317 deletions

View File

@@ -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
}

View File

@@ -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

View 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
}

View 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"))
}
}

View 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
}

View File

@@ -0,0 +1,9 @@
package serverconfigs
import "regexp"
// mime type
type MimeTypeRule struct {
Value string
Regexp *regexp.Regexp
}

View File

@@ -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

View File

@@ -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"`

View File

@@ -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)
}

View File

@@ -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
}