mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2026-05-26 00:25:20 +08:00
支持brotli和deflate压缩方式
This commit is contained in:
36
pkg/serverconfigs/http_compression_brotli_config.go
Normal file
36
pkg/serverconfigs/http_compression_brotli_config.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
|
||||
type HTTPBrotliCompressionConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
|
||||
Level int8 `yaml:"level" json:"level"` // 级别
|
||||
MinLength *shared.SizeCapacity `yaml:"minLength" json:"minLength"` // 最小压缩对象比如4m, 24k
|
||||
MaxLength *shared.SizeCapacity `yaml:"maxLength" json:"maxLength"` // 最大压缩对象
|
||||
Conds *shared.HTTPRequestCondsConfig `yaml:"conds" json:"conds"` // 匹配条件
|
||||
|
||||
minLength int64
|
||||
maxLength int64
|
||||
}
|
||||
|
||||
func (this *HTTPBrotliCompressionConfig) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
if this.MaxLength != nil {
|
||||
this.maxLength = this.MaxLength.Bytes()
|
||||
}
|
||||
|
||||
if this.Conds != nil {
|
||||
err := this.Conds.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
247
pkg/serverconfigs/http_compression_config.go
Normal file
247
pkg/serverconfigs/http_compression_config.go
Normal file
@@ -0,0 +1,247 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DefaultHTTPCompressionTypes = []HTTPCompressionType{HTTPCompressionTypeGzip, HTTPCompressionTypeDeflate, HTTPCompressionTypeBrotli}
|
||||
|
||||
type HTTPCompressionRef struct {
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
}
|
||||
|
||||
// HTTPCompressionConfig 内容压缩配置
|
||||
type HTTPCompressionConfig struct {
|
||||
IsPrior bool `yaml:"isPrior" json:"isPrior"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
|
||||
UseDefaultTypes bool `yaml:"useDefaultTypes" json:"useDefaultTypes"` // 是否使用默认的类型
|
||||
Types []HTTPCompressionType `yaml:"types" json:"types"` // 支持的类型,如果为空表示默认顺序
|
||||
Level int8 `yaml:"level" json:"level"` // 级别:1-12
|
||||
|
||||
GzipRef *HTTPCompressionRef `yaml:"gzipRef" json:"gzipRef"`
|
||||
DeflateRef *HTTPCompressionRef `yaml:"deflateRef" json:"deflateRef"`
|
||||
BrotliRef *HTTPCompressionRef `yaml:"brotliRef" json:"brotliRef"`
|
||||
|
||||
Gzip *HTTPGzipCompressionConfig `yaml:"gzip" json:"gzip"`
|
||||
Deflate *HTTPDeflateCompressionConfig `yaml:"deflate" json:"deflate"`
|
||||
Brotli *HTTPBrotliCompressionConfig `yaml:"brotli" json:"brotli"`
|
||||
|
||||
MinLength *shared.SizeCapacity `yaml:"minLength" json:"minLength"` // 最小压缩对象比如4m, 24k
|
||||
MaxLength *shared.SizeCapacity `yaml:"maxLength" json:"maxLength"` // 最大压缩对象
|
||||
MimeTypes []string `yaml:"mimeTypes" json:"mimeTypes"` // 支持的MimeType,支持image/*这样的通配符使用
|
||||
Extensions []string `yaml:"extensions" json:"extensions"` // 文件扩展名,包含点符号,不区分大小写
|
||||
Conds *shared.HTTPRequestCondsConfig `yaml:"conds" json:"conds"` // 匹配条件
|
||||
|
||||
minLength int64
|
||||
maxLength int64
|
||||
mimeTypeRules []*shared.MimeTypeRule
|
||||
extensions []string
|
||||
|
||||
types []HTTPCompressionType
|
||||
|
||||
supportGzip bool
|
||||
supportDeflate bool
|
||||
supportBrotli bool
|
||||
}
|
||||
|
||||
// Init 初始化
|
||||
func (this *HTTPCompressionConfig) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
if this.MaxLength != nil {
|
||||
this.maxLength = this.MaxLength.Bytes()
|
||||
}
|
||||
|
||||
if this.Conds != nil {
|
||||
err := this.Conds.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// mime types
|
||||
this.mimeTypeRules = []*shared.MimeTypeRule{}
|
||||
for _, mimeType := range this.MimeTypes {
|
||||
rule, err := shared.NewMimeTypeRule(mimeType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.mimeTypeRules = append(this.mimeTypeRules, rule)
|
||||
}
|
||||
|
||||
// extensions
|
||||
this.extensions = []string{}
|
||||
for _, ext := range this.Extensions {
|
||||
ext = strings.ToLower(ext)
|
||||
if len(ext) > 0 && ext[0] != '.' {
|
||||
ext = "." + ext
|
||||
}
|
||||
this.extensions = append(this.extensions, ext)
|
||||
}
|
||||
|
||||
if this.Gzip != nil {
|
||||
err := this.Gzip.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if this.Deflate != nil {
|
||||
err := this.Deflate.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if this.Brotli != nil {
|
||||
err := this.Brotli.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var supportedTypes = []HTTPCompressionType{}
|
||||
if !this.UseDefaultTypes {
|
||||
supportedTypes = append(supportedTypes, this.Types...)
|
||||
} else {
|
||||
supportedTypes = append(supportedTypes, DefaultHTTPCompressionTypes...)
|
||||
}
|
||||
this.types = supportedTypes
|
||||
|
||||
this.supportGzip = false
|
||||
this.supportDeflate = false
|
||||
this.supportDeflate = false
|
||||
for _, supportType := range supportedTypes {
|
||||
switch supportType {
|
||||
case HTTPCompressionTypeGzip:
|
||||
if this.GzipRef == nil || (this.GzipRef != nil && this.GzipRef.IsOn && this.Gzip != nil && this.Gzip.IsOn) {
|
||||
this.supportGzip = true
|
||||
}
|
||||
case HTTPCompressionTypeDeflate:
|
||||
if this.DeflateRef == nil || (this.DeflateRef != nil && this.DeflateRef.IsOn && this.Deflate != nil && this.Deflate.IsOn) {
|
||||
this.supportDeflate = true
|
||||
}
|
||||
case HTTPCompressionTypeBrotli:
|
||||
if this.BrotliRef == nil || (this.BrotliRef != nil && this.BrotliRef.IsOn && this.Brotli != nil && this.Brotli.IsOn) {
|
||||
this.supportBrotli = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MinBytes 可压缩最小尺寸
|
||||
func (this *HTTPCompressionConfig) MinBytes() int64 {
|
||||
return this.minLength
|
||||
}
|
||||
|
||||
// MaxBytes 可压缩最大尺寸
|
||||
func (this *HTTPCompressionConfig) MaxBytes() int64 {
|
||||
return this.maxLength
|
||||
}
|
||||
|
||||
// MatchResponse 是否匹配响应
|
||||
func (this *HTTPCompressionConfig) MatchResponse(mimeType string, contentLength int64, requestExt string, formatter shared.Formatter) bool {
|
||||
if this.Conds != nil && formatter != nil {
|
||||
if !this.Conds.MatchResponse(formatter) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// min length
|
||||
if this.minLength > 0 && contentLength < this.minLength {
|
||||
return false
|
||||
}
|
||||
|
||||
// max length
|
||||
if this.maxLength > 0 && contentLength > this.maxLength {
|
||||
return false
|
||||
}
|
||||
|
||||
// extensions
|
||||
if len(this.extensions) > 0 {
|
||||
if len(requestExt) > 0 {
|
||||
for _, ext := range this.extensions {
|
||||
if ext == requestExt {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mime types
|
||||
if len(this.mimeTypeRules) > 0 {
|
||||
if len(mimeType) > 0 {
|
||||
var index = strings.Index(mimeType, ";")
|
||||
if index >= 0 {
|
||||
mimeType = mimeType[:index]
|
||||
}
|
||||
for _, rule := range this.mimeTypeRules {
|
||||
if rule.Match(mimeType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有指定条件,则所有的都能压缩
|
||||
if len(this.extensions) == 0 && len(this.mimeTypeRules) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// MatchAcceptEncoding 根据Accept-Encoding选择优先的压缩方式
|
||||
func (this *HTTPCompressionConfig) MatchAcceptEncoding(acceptEncodings string) (compressionType HTTPCompressionType, compressionEncoding string, ok bool) {
|
||||
if len(acceptEncodings) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(this.types) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var pieces = strings.Split(acceptEncodings, ",")
|
||||
var encodings = []string{}
|
||||
for _, piece := range pieces {
|
||||
var qualityIndex = strings.Index(piece, ";")
|
||||
if qualityIndex >= 0 {
|
||||
// TODO 实现优先级
|
||||
piece = piece[:qualityIndex]
|
||||
}
|
||||
|
||||
encodings = append(encodings, strings.TrimSpace(piece))
|
||||
}
|
||||
|
||||
if len(encodings) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, supportType := range this.types {
|
||||
switch supportType {
|
||||
case HTTPCompressionTypeGzip:
|
||||
if this.supportGzip && lists.ContainsString(encodings, "gzip") {
|
||||
return HTTPCompressionTypeGzip, "gzip", true
|
||||
}
|
||||
case HTTPCompressionTypeDeflate:
|
||||
if this.supportDeflate && lists.ContainsString(encodings, "deflate") {
|
||||
return HTTPCompressionTypeDeflate, "deflate", true
|
||||
}
|
||||
case HTTPCompressionTypeBrotli:
|
||||
if this.supportBrotli && lists.ContainsString(encodings, "br") {
|
||||
return HTTPCompressionTypeBrotli, "br", true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", "", false
|
||||
}
|
||||
139
pkg/serverconfigs/http_compression_config_test.go
Normal file
139
pkg/serverconfigs/http_compression_config_test.go
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCompressionConfig_Init(t *testing.T) {
|
||||
{
|
||||
var config = &HTTPCompressionConfig{
|
||||
IsPrior: false,
|
||||
IsOn: false,
|
||||
Types: nil,
|
||||
Level: 0,
|
||||
MinLength: nil,
|
||||
MaxLength: nil,
|
||||
MimeTypes: nil,
|
||||
Extensions: nil,
|
||||
Conds: nil,
|
||||
}
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a := assert.NewAssertion(t)
|
||||
a.IsTrue(config.MatchResponse("text/html", 1024, "", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsTrue(config.MatchResponse("text/html", 1024, ".html", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
}
|
||||
|
||||
{
|
||||
var config = &HTTPCompressionConfig{
|
||||
IsPrior: false,
|
||||
IsOn: false,
|
||||
Types: nil,
|
||||
Level: 0,
|
||||
MinLength: nil,
|
||||
MaxLength: nil,
|
||||
MimeTypes: []string{"text/html", "text/plain"},
|
||||
Extensions: nil,
|
||||
Conds: nil,
|
||||
}
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a := assert.NewAssertion(t)
|
||||
a.IsTrue(config.MatchResponse("text/html", 1024, "", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsTrue(config.MatchResponse("text/html; charset=utf-8", 1024, ".html", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsFalse(config.MatchResponse("image/png", 1024, ".html", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
}
|
||||
|
||||
{
|
||||
var config = &HTTPCompressionConfig{
|
||||
IsPrior: false,
|
||||
IsOn: false,
|
||||
Types: nil,
|
||||
Level: 0,
|
||||
MinLength: nil,
|
||||
MaxLength: nil,
|
||||
MimeTypes: []string{"text/html", "text/plain"},
|
||||
Extensions: []string{".html", ".txt"},
|
||||
Conds: nil,
|
||||
}
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a := assert.NewAssertion(t)
|
||||
a.IsTrue(config.MatchResponse("text/html", 1024, "", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsTrue(config.MatchResponse("text/plain", 1024, ".txt", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsTrue(config.MatchResponse("text/html; charset=utf-8", 1024, ".html", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
a.IsTrue(config.MatchResponse("image/png", 1024, ".html", func(s string) string {
|
||||
return s
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPCompressionConfig_MatchAcceptEncoding(t *testing.T) {
|
||||
var config = &HTTPCompressionConfig{
|
||||
GzipRef: &HTTPCompressionRef{
|
||||
//IsOn: true,
|
||||
},
|
||||
Gzip: &HTTPGzipCompressionConfig{
|
||||
IsOn: true,
|
||||
},
|
||||
|
||||
DeflateRef: &HTTPCompressionRef{IsOn: true},
|
||||
Deflate: &HTTPDeflateCompressionConfig{IsOn: false},
|
||||
|
||||
BrotliRef: &HTTPCompressionRef{IsOn: true},
|
||||
Brotli: &HTTPBrotliCompressionConfig{IsOn: true},
|
||||
}
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, encodings := range []string{"gzip, deflate, br", "gzip, deflate", "deflate", "br", "compress", "br;q=0.8"} {
|
||||
result, encoding, ok := config.MatchAcceptEncoding(encodings)
|
||||
t.Log(encodings+" -> "+result+"/"+encoding, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPCompressionConfig_MatchAcceptEncoding2(t *testing.T) {
|
||||
var config = &HTTPCompressionConfig{
|
||||
//UseDefaultTypes: true,
|
||||
Types: []HTTPCompressionType{"brotli"},
|
||||
}
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, encodings := range []string{"gzip, deflate, br", "gzip, deflate", "deflate", "br", "compress", "br;q=0.8"} {
|
||||
result, encoding, ok := config.MatchAcceptEncoding(encodings)
|
||||
t.Log(encodings+" -> "+result+"/"+encoding, ok)
|
||||
}
|
||||
}
|
||||
36
pkg/serverconfigs/http_compression_deflate_config.go
Normal file
36
pkg/serverconfigs/http_compression_deflate_config.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
|
||||
type HTTPDeflateCompressionConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
|
||||
Level int8 `yaml:"level" json:"level"` // 级别
|
||||
MinLength *shared.SizeCapacity `yaml:"minLength" json:"minLength"` // 最小压缩对象比如4m, 24k
|
||||
MaxLength *shared.SizeCapacity `yaml:"maxLength" json:"maxLength"` // 最大压缩对象
|
||||
Conds *shared.HTTPRequestCondsConfig `yaml:"conds" json:"conds"` // 匹配条件
|
||||
|
||||
minLength int64
|
||||
maxLength int64
|
||||
}
|
||||
|
||||
func (this *HTTPDeflateCompressionConfig) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
if this.MaxLength != nil {
|
||||
this.maxLength = this.MaxLength.Bytes()
|
||||
}
|
||||
|
||||
if this.Conds != nil {
|
||||
err := this.Conds.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
)
|
||||
|
||||
// gzip配置
|
||||
type HTTPGzipConfig struct {
|
||||
// HTTPGzipCompressionConfig gzip配置
|
||||
type HTTPGzipCompressionConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Level int8 `yaml:"level" json:"level"` // 1-9
|
||||
@@ -15,11 +15,10 @@ type HTTPGzipConfig struct {
|
||||
|
||||
minLength int64
|
||||
maxLength int64
|
||||
mimeTypes []*MimeTypeRule
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPGzipConfig) Init() error {
|
||||
// Init 校验
|
||||
func (this *HTTPGzipCompressionConfig) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
@@ -37,12 +36,12 @@ func (this *HTTPGzipConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 可压缩最小尺寸
|
||||
func (this *HTTPGzipConfig) MinBytes() int64 {
|
||||
// MinBytes 可压缩最小尺寸
|
||||
func (this *HTTPGzipCompressionConfig) MinBytes() int64 {
|
||||
return this.minLength
|
||||
}
|
||||
|
||||
// 可压缩最大尺寸
|
||||
func (this *HTTPGzipConfig) MaxBytes() int64 {
|
||||
// MaxBytes 可压缩最大尺寸
|
||||
func (this *HTTPGzipCompressionConfig) MaxBytes() int64 {
|
||||
return this.maxLength
|
||||
}
|
||||
11
pkg/serverconfigs/http_compression_types.go
Normal file
11
pkg/serverconfigs/http_compression_types.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
type HTTPCompressionType = string
|
||||
|
||||
const (
|
||||
HTTPCompressionTypeGzip HTTPCompressionType = "gzip"
|
||||
HTTPCompressionTypeDeflate HTTPCompressionType = "deflate"
|
||||
HTTPCompressionTypeBrotli HTTPCompressionType = "brotli"
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGzipConfig_MatchContentType(t *testing.T) {
|
||||
|
||||
}
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type HTTPWebConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Locations []*HTTPLocationConfig `yaml:"locations" json:"locations"` // 路径规则 TODO
|
||||
LocationRefs []*HTTPLocationRef `yaml:"locationRefs" json:"locationRefs"` // 路径规则应用
|
||||
GzipRef *HTTPGzipRef `yaml:"gzipRef" json:"gzipRef"` // Gzip引用
|
||||
Gzip *HTTPGzipConfig `yaml:"gzip" json:"gzip"` // Gzip配置
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Locations []*HTTPLocationConfig `yaml:"locations" json:"locations"` // 路径规则 TODO
|
||||
LocationRefs []*HTTPLocationRef `yaml:"locationRefs" json:"locationRefs"` // 路径规则应用
|
||||
//GzipRef *HTTPGzipRef `yaml:"gzipRef" json:"gzipRef"` // Gzip引用
|
||||
//Gzip *HTTPCompressGzipConfig `yaml:"gzip" json:"gzip"` // Gzip配置
|
||||
Compression *HTTPCompressionConfig `yaml:"compression" json:"compression"` //
|
||||
Charset *HTTPCharsetConfig `yaml:"charset" json:"charset"` // 字符编码
|
||||
Shutdown *HTTPShutdownConfig `yaml:"shutdown" json:"shutdown"` // 临时关闭配置
|
||||
Pages []*HTTPPageConfig `yaml:"pages" json:"pages"` // 特殊页面配置
|
||||
@@ -61,9 +62,9 @@ func (this *HTTPWebConfig) Init() error {
|
||||
}
|
||||
}
|
||||
|
||||
// gzip
|
||||
if this.Gzip != nil {
|
||||
err := this.Gzip.Init()
|
||||
// compression
|
||||
if this.Compression != nil {
|
||||
err := this.Compression.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
import "regexp"
|
||||
|
||||
// mime type
|
||||
type MimeTypeRule struct {
|
||||
Value string
|
||||
Regexp *regexp.Regexp
|
||||
}
|
||||
5
pkg/serverconfigs/shared/formatter.go
Normal file
5
pkg/serverconfigs/shared/formatter.go
Normal file
@@ -0,0 +1,5 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package shared
|
||||
|
||||
type Formatter = func(s string) string
|
||||
@@ -40,8 +40,8 @@ func (this *HTTPRequestCondsConfig) Init() error {
|
||||
}
|
||||
|
||||
// MatchRequest 判断请求是否匹配
|
||||
func (this *HTTPRequestCondsConfig) MatchRequest(formatter func(s string) string) bool {
|
||||
if !this.IsOn && len(this.Groups) == 0 {
|
||||
func (this *HTTPRequestCondsConfig) MatchRequest(formatter Formatter) bool {
|
||||
if !this.IsOn || len(this.Groups) == 0 {
|
||||
return true
|
||||
}
|
||||
ok := false
|
||||
@@ -63,7 +63,7 @@ func (this *HTTPRequestCondsConfig) MatchRequest(formatter func(s string) string
|
||||
|
||||
// MatchResponse 判断响应是否匹配
|
||||
func (this *HTTPRequestCondsConfig) MatchResponse(formatter func(s string) string) bool {
|
||||
if !this.IsOn && len(this.Groups) == 0 {
|
||||
if !this.IsOn || len(this.Groups) == 0 {
|
||||
return true
|
||||
}
|
||||
ok := false
|
||||
|
||||
43
pkg/serverconfigs/shared/mime_type_rule.go
Normal file
43
pkg/serverconfigs/shared/mime_type_rule.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MimeTypeRule mime type规则
|
||||
type MimeTypeRule struct {
|
||||
Value string
|
||||
|
||||
isAll bool
|
||||
regexp *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewMimeTypeRule(mimeType string) (*MimeTypeRule, error) {
|
||||
mimeType = strings.ToLower(mimeType)
|
||||
|
||||
var rule = &MimeTypeRule{
|
||||
Value: mimeType,
|
||||
}
|
||||
if mimeType == "*/*" || mimeType == "*" {
|
||||
rule.isAll = true
|
||||
} else if strings.Contains(mimeType, "*") {
|
||||
mimeType = strings.ReplaceAll(regexp.QuoteMeta(mimeType), `\*`, ".+")
|
||||
reg, err := regexp.Compile("^(?i)" + mimeType + "$")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rule.regexp = reg
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
func (this *MimeTypeRule) Match(mimeType string) bool {
|
||||
if this.isAll {
|
||||
return true
|
||||
}
|
||||
if this.regexp == nil {
|
||||
return this.Value == strings.ToLower(mimeType)
|
||||
}
|
||||
return this.regexp.MatchString(mimeType)
|
||||
}
|
||||
49
pkg/serverconfigs/shared/mime_type_rule_test.go
Normal file
49
pkg/serverconfigs/shared/mime_type_rule_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package shared
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMimeTypeRule_Match(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
rule, err := NewMimeTypeRule("text/plain")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(rule.Match("text/plain"))
|
||||
a.IsTrue(rule.Match("TEXT/plain"))
|
||||
a.IsFalse(rule.Match("text/html"))
|
||||
}
|
||||
|
||||
{
|
||||
rule, err := NewMimeTypeRule("image/*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(rule.Match("image/png"))
|
||||
a.IsTrue(rule.Match("IMAGE/jpeg"))
|
||||
a.IsFalse(rule.Match("image/"))
|
||||
a.IsFalse(rule.Match("image1/png"))
|
||||
a.IsFalse(rule.Match("x-image/png"))
|
||||
}
|
||||
|
||||
{
|
||||
_, err := NewMimeTypeRule("x-image/*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
rule, err := NewMimeTypeRule("*/*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(rule.Match("any/thing"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user