Files
EdgeCommon/pkg/serverconfigs/http_cache_ref.go
GoEdgeLab 2f3981704e v1.4.1
2024-07-27 13:29:26 +08:00

159 lines
5.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package serverconfigs
import (
"net/http"
"strings"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/lists"
)
var DefaultSkippedResponseCacheControlValues = []string{"private", "no-cache", "no-store"}
type HTTPCacheRef struct {
IsOn bool `yaml:"isOn" json:"isOn"`
CachePolicyId int64 `yaml:"cachePolicyId" json:"cachePolicyId"`
Key string `yaml:"key" json:"key"` // 每个缓存的Key规则里面可以有变量
Life *shared.TimeDuration `yaml:"life" json:"life"` // 时间
ExpiresTime *HTTPExpiresTimeConfig `yaml:"expiresTime" json:"expiresTime"` // 客户端过期时间
Status []int `yaml:"status" json:"status"` // 缓存的状态码列表
MinSize *shared.SizeCapacity `yaml:"minSize" json:"minSize"` // 能够缓存的最小尺寸
MaxSize *shared.SizeCapacity `yaml:"maxSize" json:"maxSize"` // 能够缓存的最大尺寸
Methods []string `yaml:"methods" json:"methods"` // 支持的请求方法
SkipResponseCacheControlValues []string `yaml:"skipCacheControlValues" json:"skipCacheControlValues"` // 可以跳过的响应的Cache-Control值
SkipResponseSetCookie bool `yaml:"skipSetCookie" json:"skipSetCookie"` // 是否跳过响应的Set-Cookie Header
EnableRequestCachePragma bool `yaml:"enableRequestCachePragma" json:"enableRequestCachePragma"` // 是否支持客户端的Pragma: no-cache
AllowChunkedEncoding bool `yaml:"allowChunkedEncoding" json:"allowChunkedEncoding"` // 是否允许分片内容
AllowPartialContent bool `yaml:"allowPartialContent" json:"allowPartialContent"` // 支持分段内容缓存
ForcePartialContent bool `yaml:"forcePartialContent" json:"forcePartialContent"` // 强制分段内容优先
AlwaysForwardRangeRequest bool `yaml:"alwaysForwardRangeRequest" json:"alwaysForwardRangeRequest"` // 强制Range请求回源
EnableIfNoneMatch bool `yaml:"enableIfNoneMatch" json:"enableIfNoneMatch"` // 支持If-None-match
EnableIfModifiedSince bool `yaml:"enableIfModifiedSince" json:"enableIfModifiedSince"` // 支持If-Modified-Since
EnableReadingOriginAsync bool `yaml:"enableReadingOriginAsync" json:"enableReadingOriginAsync"` // 允许异步读取源站
Conds *shared.HTTPRequestCondsConfig `yaml:"conds" json:"conds"` // 复杂请求条件组合
SimpleCond *shared.HTTPRequestCond `yaml:"simpleCond" json:"simpleCond"` // 简单条件
CachePolicy *HTTPCachePolicy `yaml:"cachePolicy" json:"cachePolicy"`
IsReverse bool `yaml:"isReverse" json:"isReverse"` // 是否为反向条件,反向条件的不缓存
lifeSeconds int64
minSize int64
maxSize int64
uppercaseSkipCacheControlValues []string
methodMap map[string]bool
statusList []int
}
func (this *HTTPCacheRef) Init() error {
if this.MinSize != nil {
this.minSize = this.MinSize.Bytes()
}
if this.MaxSize != nil {
this.maxSize = this.MaxSize.Bytes()
}
if this.Life != nil {
this.lifeSeconds = int64(this.Life.Duration().Seconds())
}
// control-values
this.uppercaseSkipCacheControlValues = []string{}
for _, value := range this.SkipResponseCacheControlValues {
this.uppercaseSkipCacheControlValues = append(this.uppercaseSkipCacheControlValues, strings.ToUpper(value))
}
// conds
if this.Conds != nil {
err := this.Conds.Init()
if err != nil {
return err
}
}
if this.SimpleCond != nil {
err := this.SimpleCond.Init()
if err != nil {
return err
}
}
// policy
if this.CachePolicy != nil {
err := this.CachePolicy.Init()
if err != nil {
return err
}
}
// methods
this.methodMap = map[string]bool{}
if len(this.Methods) > 0 {
for _, method := range this.Methods {
this.methodMap[strings.ToUpper(method)] = true
}
}
// status
this.statusList = this.Status
if this.AllowPartialContent {
if !lists.ContainsInt(this.statusList, http.StatusPartialContent) {
this.statusList = append(this.statusList, http.StatusPartialContent)
}
} else if lists.ContainsInt(this.statusList, http.StatusPartialContent) {
this.AllowPartialContent = true
}
return nil
}
// MaxSizeBytes 最大数据尺寸
func (this *HTTPCacheRef) MaxSizeBytes() int64 {
return this.maxSize
}
// MinSizeBytes 最小数据尺寸
func (this *HTTPCacheRef) MinSizeBytes() int64 {
return this.minSize
}
// LifeSeconds 生命周期
func (this *HTTPCacheRef) LifeSeconds() int64 {
return this.lifeSeconds
}
// ContainsCacheControl 是否包含某个Cache-Control值
func (this *HTTPCacheRef) ContainsCacheControl(value string) bool {
return lists.ContainsString(this.uppercaseSkipCacheControlValues, strings.ToUpper(value))
}
// MatchRequest 匹配请求
func (this *HTTPCacheRef) MatchRequest(req *http.Request) bool {
// 请求方法
if len(this.methodMap) > 0 {
_, ok := this.methodMap[req.Method]
if !ok {
return false
}
}
return true
}
// MatchStatus 检查是否包含某个状态码
func (this *HTTPCacheRef) MatchStatus(statusCode int) bool {
if len(this.statusList) == 0 {
return true
}
for _, status := range this.statusList {
if status == statusCode {
return true
}
}
return false
}