实现HTTP部分功能
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
type ComponentConfig struct {
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
|
||||
var UsualCharsets = []maps.Map{
|
||||
{"charset": "utf-8", "name": "Universal Alphabet (UTF-8)"},
|
||||
{"charset": "unicode", "name": "Unicode"},
|
||||
{"name": "Chinese Simplified (GB2312)", "charset": "gb2312"},
|
||||
{"charset": "big5", "name": "Chinese Traditional (Big5)"},
|
||||
{"charset": "iso-8859-1", "name": "Western Alphabet"},
|
||||
{"charset": "euc-kr", "name": "Korean (EUC)"},
|
||||
{"charset": "shift-jis", "name": "Japanese (Shift-JIS)"},
|
||||
{"charset": "us-ascii", "name": "US-ASCII"},
|
||||
}
|
||||
|
||||
// 数据来自 https://webcheatsheet.com/html/character_sets_list.php
|
||||
var BasicCharsets = []maps.Map{
|
||||
{"name": "Chinese Traditional (Big5)", "charset": "big5"},
|
||||
{"charset": "euc-kr", "name": "Korean (EUC)"},
|
||||
{"charset": "iso-8859-1", "name": "Western Alphabet"},
|
||||
{"charset": "iso-8859-2", "name": "Central European Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-3", "name": "Latin 3 Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-4", "name": "Baltic Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-5", "name": "Cyrillic Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-6", "name": "Arabic Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-7", "name": "Greek Alphabet (ISO)"},
|
||||
{"charset": "iso-8859-8", "name": "Hebrew Alphabet (ISO)"},
|
||||
{"charset": "koi8-r", "name": "Cyrillic Alphabet (KOI8-R)"},
|
||||
{"charset": "shift-jis", "name": "Japanese (Shift-JIS)"},
|
||||
{"name": "Japanese (EUC)", "charset": "x-euc"},
|
||||
{"charset": "utf-8", "name": "Universal Alphabet (UTF-8)"},
|
||||
{"charset": "windows-1250", "name": "Central European Alphabet (Windows)"},
|
||||
{"charset": "windows-1251", "name": "Cyrillic Alphabet (Windows)"},
|
||||
{"charset": "windows-1252", "name": "Western Alphabet (Windows)"},
|
||||
{"charset": "windows-1253", "name": "Greek Alphabet (Windows)"},
|
||||
{"charset": "windows-1254", "name": "Turkish Alphabet"},
|
||||
{"charset": "windows-1255", "name": "Hebrew Alphabet (Windows)"},
|
||||
{"charset": "windows-1256", "name": "Arabic Alphabet (Windows)"},
|
||||
{"charset": "windows-1257", "name": "Baltic Alphabet (Windows)"},
|
||||
{"charset": "windows-1258", "name": "Vietnamese Alphabet (Windows)"},
|
||||
{"charset": "windows-874", "name": "Thai (Windows)"},
|
||||
}
|
||||
|
||||
var AllCharsets = []maps.Map{
|
||||
{"charset": "ASMO-708", "name": "Arabic (ASMO 708)"},
|
||||
{"charset": "DOS-720", "name": "Arabic (DOS)"},
|
||||
{"charset": "iso-8859-6", "name": "Arabic (ISO)"},
|
||||
{"charset": "x-mac-arabic", "name": "Arabic (Mac)"},
|
||||
{"charset": "windows-1256", "name": "Arabic (Windows)"},
|
||||
{"charset": "ibm775", "name": "Baltic (DOS)"},
|
||||
{"charset": "iso-8859-4", "name": "Baltic (ISO)"},
|
||||
{"charset": "windows-1257", "name": "Baltic (Windows)"},
|
||||
{"charset": "ibm852", "name": "Central European (DOS)"},
|
||||
{"name": "Central European (ISO)", "charset": "iso-8859-2"},
|
||||
{"charset": "x-mac-ce", "name": "Central European (Mac)"},
|
||||
{"charset": "windows-1250", "name": "Central European (Windows)"},
|
||||
{"name": "Chinese Simplified (EUC)", "charset": "EUC-CN"},
|
||||
{"name": "Chinese Simplified (GB2312)", "charset": "gb2312"},
|
||||
{"charset": "hz-gb-2312", "name": "Chinese Simplified (HZ)"},
|
||||
{"charset": "x-mac-chinesesimp", "name": "Chinese Simplified (Mac)"},
|
||||
{"charset": "big5", "name": "Chinese Traditional (Big5)"},
|
||||
{"name": "Chinese Traditional (CNS)", "charset": "x-Chinese-CNS"},
|
||||
{"charset": "x-Chinese-Eten", "name": "Chinese Traditional (Eten)"},
|
||||
{"charset": "x-mac-chinesetrad", "name": "Chinese Traditional (Mac)"},
|
||||
{"charset": "950", "name": "Chinese Traditional (Mac)"},
|
||||
{"charset": "cp866", "name": "Cyrillic (DOS)"},
|
||||
{"charset": "iso-8859-5", "name": "Cyrillic (ISO)"},
|
||||
{"charset": "koi8-r", "name": "Cyrillic (KOI8-R)"},
|
||||
{"charset": "koi8-u", "name": "Cyrillic (KOI8-U)"},
|
||||
{"charset": "x-mac-cyrillic", "name": "Cyrillic (Mac)"},
|
||||
{"charset": "windows-1251", "name": "Cyrillic (Windows)"},
|
||||
{"charset": "x-Europa", "name": "Europa"},
|
||||
{"charset": "x-IA5-German", "name": "German (IA5)"},
|
||||
{"charset": "ibm737", "name": "Greek (DOS)"},
|
||||
{"name": "Greek (ISO)", "charset": "iso-8859-7"},
|
||||
{"name": "Greek (Mac)", "charset": "x-mac-greek"},
|
||||
{"charset": "windows-1253", "name": "Greek (Windows)"},
|
||||
{"charset": " ", "name": "Greek (Windows)"},
|
||||
{"charset": "ibm869", "name": "Greek, Modern (DOS)"},
|
||||
{"name": "Hebrew (DOS)", "charset": "DOS-862"},
|
||||
{"charset": "iso-8859-8-i", "name": "Hebrew (ISO-Logical)"},
|
||||
{"charset": "iso-8859-8", "name": "Hebrew (ISO-Visual)"},
|
||||
{"charset": "x-mac-hebrew", "name": "Hebrew (Mac)"},
|
||||
{"charset": "windows-1255", "name": "Hebrew (Windows)"},
|
||||
{"charset": "x-EBCDIC-Arabic", "name": "IBM EBCDIC (Arabic)"},
|
||||
{"charset": "x-EBCDIC-CyrillicRussian", "name": "IBM EBCDIC (Cyrillic Russian)"},
|
||||
{"charset": "x-EBCDIC-CyrillicSerbianBulgarian", "name": "IBM EBCDIC (Cyrillic Serbian-Bulgarian)"},
|
||||
{"charset": "x-EBCDIC-DenmarkNorway", "name": "IBM EBCDIC (Denmark-Norway)"},
|
||||
{"charset": "x-ebcdic-denmarknorway-euro", "name": "IBM EBCDIC (Denmark-Norway-Euro)"},
|
||||
{"charset": "x-EBCDIC-FinlandSweden", "name": "IBM EBCDIC (Finland-Sweden)"},
|
||||
{"charset": "x-ebcdic-finlandsweden-euro", "name": "IBM EBCDIC (Finland-Sweden-Euro)"},
|
||||
{"charset": "x-ebcdic-finlandsweden-euro", "name": "IBM EBCDIC (Finland-Sweden-Euro)"},
|
||||
{"charset": "x-ebcdic-france-euro", "name": "IBM EBCDIC (France-Euro)"},
|
||||
{"charset": "x-EBCDIC-Germany", "name": "IBM EBCDIC (Germany)"},
|
||||
{"charset": "x-ebcdic-germany-euro", "name": "IBM EBCDIC (Germany-Euro)"},
|
||||
{"charset": "x-EBCDIC-GreekModern", "name": "IBM EBCDIC (Greek Modern)"},
|
||||
{"charset": "x-EBCDIC-Greek", "name": "IBM EBCDIC (Greek)"},
|
||||
{"charset": "x-EBCDIC-Hebrew", "name": "IBM EBCDIC (Hebrew)"},
|
||||
{"charset": "x-EBCDIC-Icelandic", "name": "IBM EBCDIC (Icelandic)"},
|
||||
{"charset": "x-ebcdic-icelandic-euro", "name": "IBM EBCDIC (Icelandic-Euro)"},
|
||||
{"name": "IBM EBCDIC (International-Euro)", "charset": "x-ebcdic-international-euro"},
|
||||
{"charset": "x-EBCDIC-Italy", "name": "IBM EBCDIC (Italy)"},
|
||||
{"charset": "x-ebcdic-italy-euro", "name": "IBM EBCDIC (Italy-Euro)"},
|
||||
{"charset": "x-EBCDIC-JapaneseAndKana", "name": "IBM EBCDIC (Japanese and Japanese Katakana)"},
|
||||
{"charset": "x-EBCDIC-JapaneseAndJapaneseLatin", "name": "IBM EBCDIC (Japanese and Japanese-Latin)"},
|
||||
{"name": "IBM EBCDIC (Japanese and US-Canada)", "charset": "x-EBCDIC-JapaneseAndUSCanada"},
|
||||
{"name": "IBM EBCDIC (Japanese katakana)", "charset": "x-EBCDIC-JapaneseKatakana"},
|
||||
{"charset": "x-EBCDIC-KoreanAndKoreanExtended", "name": "IBM EBCDIC (Korean and Korean Extended)"},
|
||||
{"charset": "x-EBCDIC-KoreanExtended", "name": "IBM EBCDIC (Korean Extended)"},
|
||||
{"charset": "CP870", "name": "IBM EBCDIC (Multilingual Latin-2)"},
|
||||
{"charset": "x-EBCDIC-SimplifiedChinese", "name": "IBM EBCDIC (Simplified Chinese)"},
|
||||
{"charset": "X-EBCDIC-Spain", "name": "IBM EBCDIC (Spain)"},
|
||||
{"charset": "x-ebcdic-spain-euro", "name": "IBM EBCDIC (Spain-Euro)"},
|
||||
{"charset": "x-EBCDIC-Thai", "name": "IBM EBCDIC (Thai)"},
|
||||
{"charset": "x-EBCDIC-TraditionalChinese", "name": "IBM EBCDIC (Traditional Chinese)"},
|
||||
{"charset": "CP1026", "name": "IBM EBCDIC (Turkish Latin-5)"},
|
||||
{"charset": "x-EBCDIC-Turkish", "name": "IBM EBCDIC (Turkish)"},
|
||||
{"charset": "x-EBCDIC-UK", "name": "IBM EBCDIC (UK)"},
|
||||
{"charset": "x-ebcdic-uk-euro", "name": "IBM EBCDIC (UK-Euro)"},
|
||||
{"charset": "ebcdic-cp-us", "name": "IBM EBCDIC (US-Canada)"},
|
||||
{"name": "IBM EBCDIC (US-Canada-Euro)", "charset": "x-ebcdic-cp-us-euro"},
|
||||
{"charset": "ibm861", "name": "Icelandic (DOS)"},
|
||||
{"charset": "x-mac-icelandic", "name": "Icelandic (Mac)"},
|
||||
{"charset": "x-iscii-as", "name": "ISCII Assamese"},
|
||||
{"charset": "x-iscii-be", "name": "ISCII Bengali"},
|
||||
{"charset": "x-iscii-de", "name": "ISCII Devanagari"},
|
||||
{"charset": "x-iscii-gu", "name": "ISCII Gujarathi"},
|
||||
{"charset": "x-iscii-ka", "name": "ISCII Kannada"},
|
||||
{"charset": "x-iscii-ma", "name": "ISCII Malayalam"},
|
||||
{"charset": "x-iscii-or", "name": "ISCII Oriya"},
|
||||
{"charset": "x-iscii-pa", "name": "ISCII Panjabi"},
|
||||
{"charset": "x-iscii-ta", "name": "ISCII Tamil"},
|
||||
{"charset": "x-iscii-te", "name": "ISCII Telugu"},
|
||||
{"charset": "euc-jp", "name": "Japanese (EUC)"},
|
||||
{"charset": "x-euc-jp", "name": "Japanese (EUC)"},
|
||||
{"charset": "iso-2022-jp", "name": "Japanese (JIS)"},
|
||||
{"charset": "iso-2022-jp", "name": "Japanese (JIS-Allow 1 byte Kana - SO/SI)"},
|
||||
{"charset": "csISO2022JP", "name": "Japanese (JIS-Allow 1 byte Kana)"},
|
||||
{"charset": "x-mac-japanese", "name": "Japanese (Mac)"},
|
||||
{"charset": "shift_jis", "name": "Japanese (Shift-JIS)"},
|
||||
{"charset": "ks_c_5601-1987", "name": "Korean"},
|
||||
{"charset": "euc-kr", "name": "Korean (EUC)"},
|
||||
{"charset": "iso-2022-kr", "name": "Korean (ISO)"},
|
||||
{"charset": "Johab", "name": "Korean (Johab)"},
|
||||
{"charset": "x-mac-korean", "name": "Korean (Mac)"},
|
||||
{"charset": "iso-8859-3", "name": "Latin 3 (ISO)"},
|
||||
{"charset": "iso-8859-15", "name": "Latin 9 (ISO)"},
|
||||
{"charset": "x-IA5-Norwegian", "name": "Norwegian (IA5)"},
|
||||
{"charset": "IBM437", "name": "OEM United States"},
|
||||
{"charset": "x-IA5-Swedish", "name": "Swedish (IA5)"},
|
||||
{"charset": "windows-874", "name": "Thai (Windows)"},
|
||||
{"charset": "ibm857", "name": "Turkish (DOS)"}, {"charset": "iso-8859-9", "name": "Turkish (ISO)"},
|
||||
{"charset": "x-mac-turkish", "name": "Turkish (Mac)"},
|
||||
{"charset": "windows-1254", "name": "Turkish (Windows)"},
|
||||
{"charset": "unicode", "name": "Unicode"},
|
||||
{"charset": "unicodeFFFE", "name": "Unicode (Big-Endian)"},
|
||||
{"charset": "utf-7", "name": "Unicode (UTF-7)"},
|
||||
{"name": "Unicode (UTF-8)", "charset": "utf-8"},
|
||||
{"charset": "us-ascii", "name": "US-ASCII"},
|
||||
{"charset": "windows-1258", "name": "Vietnamese (Windows)"},
|
||||
{"charset": "ibm850", "name": "Western European (DOS)"},
|
||||
{"charset": "x-IA5", "name": "Western European (IA5)"},
|
||||
{"charset": "iso-8859-1", "name": "Western European (ISO)"},
|
||||
{"name": "Western European (Mac)", "charset": "macintosh"},
|
||||
{"charset": "Windows-1252", "name": "Western European (Windows)"},
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// 拷贝同类型struct指针对象中的字段
|
||||
func CopyStructObject(destPtr, sourcePtr interface{}) {
|
||||
value := reflect.ValueOf(destPtr)
|
||||
value2 := reflect.ValueOf(sourcePtr)
|
||||
|
||||
countFields := value2.Elem().NumField()
|
||||
for i := 0; i < countFields; i++ {
|
||||
v := value2.Elem().Field(i)
|
||||
if !v.IsValid() || !v.CanSet() {
|
||||
continue
|
||||
}
|
||||
value.Elem().Field(i).Set(v)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCopyStructObject(t *testing.T) {
|
||||
type Book struct {
|
||||
Name string
|
||||
Price int
|
||||
Year int
|
||||
Author string
|
||||
press string
|
||||
}
|
||||
|
||||
book1 := &Book{
|
||||
Name: "Hello Golang",
|
||||
Price: 100,
|
||||
Year: 2020,
|
||||
Author: "Liu",
|
||||
press: "Beijing",
|
||||
}
|
||||
book2 := new(Book)
|
||||
CopyStructObject(book2, book1)
|
||||
logs.PrintAsJSON(book2, t)
|
||||
logs.PrintAsJSON(book1, t)
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/utils/string"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 从一组规则中匹配域名
|
||||
// 支持的格式:example.com, www.example.com, .example.com, *.example.com, ~(\d+).example.com
|
||||
// 更多参考:http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
|
||||
func MatchDomains(patterns []string, domain string) (isMatched bool) {
|
||||
if len(patterns) == 0 {
|
||||
return
|
||||
}
|
||||
for _, pattern := range patterns {
|
||||
if matchDomain(pattern, domain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 匹配单个域名规则
|
||||
func matchDomain(pattern string, domain string) (isMatched bool) {
|
||||
if len(pattern) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
if pattern[0] == '~' {
|
||||
reg, err := stringutil.RegexpCompile(strings.TrimSpace(pattern[1:]))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return false
|
||||
}
|
||||
return reg.MatchString(domain)
|
||||
}
|
||||
|
||||
if pattern[0] == '.' {
|
||||
return strings.HasSuffix(domain, pattern)
|
||||
}
|
||||
|
||||
// 其他匹配
|
||||
patternPieces := strings.Split(pattern, ".")
|
||||
domainPieces := strings.Split(domain, ".")
|
||||
if len(patternPieces) != len(domainPieces) {
|
||||
return
|
||||
}
|
||||
isMatched = true
|
||||
for index, patternPiece := range patternPieces {
|
||||
if patternPiece == "" || patternPiece == "*" || patternPiece == domainPieces[index] {
|
||||
continue
|
||||
}
|
||||
isMatched = false
|
||||
break
|
||||
}
|
||||
return isMatched
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMatchDomain(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
{
|
||||
ok := MatchDomains([]string{}, "example.com")
|
||||
a.IsFalse(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"example.com"}, "example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"www.example.com"}, "example.com")
|
||||
a.IsFalse(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{".example.com"}, "www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{".example.com"}, "a.www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{".example.com"}, "a.www.example123.com")
|
||||
a.IsFalse(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"*.example.com"}, "www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"*.*.com"}, "www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"www.*.com"}, "www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"gallery.*.com"}, "www.example.com")
|
||||
a.IsFalse(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"~\\w+.example.com"}, "www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"~\\w+.example.com"}, "a.www.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"~^\\d+.example.com$"}, "www.example.com")
|
||||
a.IsFalse(ok)
|
||||
}
|
||||
|
||||
{
|
||||
ok := MatchDomains([]string{"~^\\d+.example.com$"}, "123.example.com")
|
||||
a.IsTrue(ok)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import "github.com/iwind/TeaGo/logs"
|
||||
|
||||
// 记录错误
|
||||
func LogError(arg ...interface{}) {
|
||||
if len(arg) == 0 {
|
||||
return
|
||||
}
|
||||
logs.Println(arg...)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var whitespaceReg = regexp.MustCompile(`\s+`)
|
||||
|
||||
// 关键词匹配
|
||||
func MatchKeyword(source, keyword string) bool {
|
||||
if len(keyword) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
pieces := whitespaceReg.Split(keyword, -1)
|
||||
source = strings.ToLower(source)
|
||||
for _, piece := range pieces {
|
||||
if strings.Index(source, strings.ToLower(piece)) > -1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMatchKeyword(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
a.IsTrue(MatchKeyword("a b c", "a"))
|
||||
a.IsFalse(MatchKeyword("a b c", ""))
|
||||
a.IsTrue(MatchKeyword("abc", "BC"))
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package configutils
|
||||
|
||||
import (
|
||||
"github.com/go-yaml/yaml"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func UnmarshalYamlFile(file string, ptr interface{}) error {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return yaml.Unmarshal(data, ptr)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
type FilterConfig struct {
|
||||
}
|
||||
@@ -1,13 +1,5 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
)
|
||||
|
||||
var globalConfig *GlobalConfig = nil
|
||||
var globalConfigFile = "global.yaml"
|
||||
|
||||
// 全局设置
|
||||
type GlobalConfig struct {
|
||||
HTTPAll struct {
|
||||
@@ -22,22 +14,6 @@ type GlobalConfig struct {
|
||||
UDP struct{} `yaml:"udp" json:"udp"`
|
||||
}
|
||||
|
||||
func SharedGlobalConfig() *GlobalConfig {
|
||||
shared.Locker.Lock()
|
||||
defer shared.Locker.Unlock()
|
||||
|
||||
if globalConfig != nil {
|
||||
return globalConfig
|
||||
}
|
||||
|
||||
err := configutils.UnmarshalYamlFile(globalConfigFile, globalConfig)
|
||||
if err != nil {
|
||||
configutils.LogError("[SharedGlobalConfig]" + err.Error())
|
||||
globalConfig = &GlobalConfig{}
|
||||
}
|
||||
return globalConfig
|
||||
}
|
||||
|
||||
func (this *GlobalConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
// 日志存储策略
|
||||
// 存储在configs/accesslog.storage.$id.conf
|
||||
type HTTPAccessLogStoragePolicy struct {
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
Type string `yaml:"type" json:"type"` // 存储类型
|
||||
Options map[string]interface{} `yaml:"options" json:"options"` // 存储选项
|
||||
Conds []*shared.RequestCond `yaml:"conds" json:"conds"` // 请求条件
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
Type string `yaml:"type" json:"type"` // 存储类型
|
||||
Options map[string]interface{} `yaml:"options" json:"options"` // 存储选项
|
||||
CondGroups []*shared.HTTPRequestCondGroup `yaml:"condGroups" json:"condsGroups"` // 请求条件
|
||||
}
|
||||
|
||||
// 创建新策略
|
||||
@@ -49,8 +49,8 @@ func NewAccessLogStoragePolicyFromId(id string) *HTTPAccessLogStoragePolicy {
|
||||
// 校验
|
||||
func (this *HTTPAccessLogStoragePolicy) Init() error {
|
||||
// cond
|
||||
if len(this.Conds) > 0 {
|
||||
for _, cond := range this.Conds {
|
||||
if len(this.CondGroups) > 0 {
|
||||
for _, cond := range this.CondGroups {
|
||||
err := cond.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -95,10 +95,10 @@ func (this *HTTPAccessLogStoragePolicy) MatchKeyword(keyword string) (matched bo
|
||||
|
||||
// 匹配条件
|
||||
func (this *HTTPAccessLogStoragePolicy) MatchConds(formatter func(string) string) bool {
|
||||
if len(this.Conds) == 0 {
|
||||
if len(this.CondGroups) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, cond := range this.Conds {
|
||||
for _, cond := range this.CondGroups {
|
||||
if !cond.Match(formatter) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
@@ -29,7 +29,7 @@ type HTTPCachePolicy struct {
|
||||
SkipResponseSetCookie bool `yaml:"skipSetCookie" json:"skipSetCookie"` // 是否跳过响应的Set-Cookie Header
|
||||
EnableRequestCachePragma bool `yaml:"enableRequestCachePragma" json:"enableRequestCachePragma"` // 是否支持客户端的Pragma: no-cache
|
||||
|
||||
Cond []*shared.RequestCond `yaml:"cond" json:"cond"`
|
||||
CondGroups []*shared.HTTPRequestCondGroup `yaml:"condGroups" json:"condGroups"`
|
||||
|
||||
life time.Duration
|
||||
maxSize int64
|
||||
@@ -86,8 +86,8 @@ func (this *HTTPCachePolicy) Init() error {
|
||||
}
|
||||
|
||||
// cond
|
||||
if len(this.Cond) > 0 {
|
||||
for _, cond := range this.Cond {
|
||||
if len(this.CondGroups) > 0 {
|
||||
for _, cond := range this.CondGroups {
|
||||
err := cond.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -5,3 +5,7 @@ type HTTPCacheRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
CachePolicyId int64 `yaml:"cachePolicyId" json:"cachePolicyId"` // 缓存策略ID
|
||||
}
|
||||
|
||||
func (this *HTTPCacheRef) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,3 +5,7 @@ type HTTPCharsetConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Charset string `yaml:"charset" json:"charset"` // 字符集
|
||||
}
|
||||
|
||||
func (this *HTTPCharsetConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
8
pkg/serverconfigs/http_filter_config.go
Normal file
8
pkg/serverconfigs/http_filter_config.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package serverconfigs
|
||||
|
||||
type HTTPFilterPolicy struct {
|
||||
}
|
||||
|
||||
func (this *HTTPFilterPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
11
pkg/serverconfigs/http_filter_ref.go
Normal file
11
pkg/serverconfigs/http_filter_ref.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package serverconfigs
|
||||
|
||||
type HTTPFilterRef struct {
|
||||
IsPrior bool `yaml:"isPrior" json:"isPrior"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
FilterPolicyId int64 `yaml:"filterPolicyId" json:"filterPolicyId"`
|
||||
}
|
||||
|
||||
func (this *HTTPFilterRef) Init() error {
|
||||
return nil
|
||||
}
|
||||
@@ -5,3 +5,7 @@ type HTTPFirewallRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
FirewallPolicyId int64 `yaml:"firewallPolicyId" json:"firewallPolicyId"`
|
||||
}
|
||||
|
||||
func (this *HTTPFirewallRef) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type HTTPLocationConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Pattern string `yaml:"pattern" json:"pattern"` // 匹配规则 TODO 未来支持更多样的匹配规则
|
||||
Name string `yaml:"name" json:"name"` // 名称
|
||||
Web *HTTPWebConfig `yaml:"web" json:"web"` // Web配置
|
||||
URLPrefix string `yaml:"urlPrefix" json:"urlPrefix"` // 实际的URL前缀,TODO 未来支持变量
|
||||
Description string `yaml:"description" json:"description"` // 描述
|
||||
ReverseProxyRef *ReverseProxyRef `yaml:"reverseProxyRef" json:"reverseProxyRef"` // 反向代理引用
|
||||
ReverseProxy *ReverseProxyConfig `yaml:"reverseProxy" json:"reverseProxy"` // 反向代理设置
|
||||
IsBreak bool `yaml:"isBreak" json:"isBreak"` // 终止向下解析
|
||||
Children []*HTTPLocationConfig `yaml:"children" json:"children"` // 子规则
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Pattern string `yaml:"pattern" json:"pattern"` // 匹配规则 TODO 未来支持更多样的匹配规则
|
||||
Name string `yaml:"name" json:"name"` // 名称
|
||||
Web *HTTPWebConfig `yaml:"web" json:"web"` // Web配置
|
||||
URLPrefix string `yaml:"urlPrefix" json:"urlPrefix"` // 实际的URL前缀,TODO 未来支持变量
|
||||
Description string `yaml:"description" json:"description"` // 描述
|
||||
ReverseProxyRef *ReverseProxyRef `yaml:"reverseProxyRef" json:"reverseProxyRef"` // 反向代理引用
|
||||
ReverseProxy *ReverseProxyConfig `yaml:"reverseProxy" json:"reverseProxy"` // 反向代理设置
|
||||
IsBreak bool `yaml:"isBreak" json:"isBreak"` // 终止向下解析
|
||||
Children []*HTTPLocationConfig `yaml:"children" json:"children"` // 子规则
|
||||
CondGroups []*shared.HTTPRequestCondGroup `yaml:"condGroups" json:"condGroups"` // 匹配条件 TODO
|
||||
AutoFlush bool `yaml:"autoFlush" json:"autoFlush"` // 自动Flush TODO
|
||||
|
||||
patternType HTTPLocationPatternType // 规则类型:LocationPattern*
|
||||
prefix string // 前缀
|
||||
@@ -55,6 +59,14 @@ func (this *HTTPLocationConfig) Init() error {
|
||||
}
|
||||
}
|
||||
|
||||
// conds
|
||||
for _, group := range this.CondGroups {
|
||||
err := group.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -209,3 +221,81 @@ func (this *HTTPLocationConfig) parsePattern() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断是否匹配路径
|
||||
// TODO 支持子Location
|
||||
func (this *HTTPLocationConfig) Match(path string, formatter func(source string) string) (vars map[string]string, isMatched bool) {
|
||||
// 判断条件
|
||||
if len(this.CondGroups) > 0 {
|
||||
for _, condGroup := range this.CondGroups {
|
||||
if !condGroup.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
if !condGroup.Match(formatter) {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if this.patternType == HTTPLocationPatternTypePrefix {
|
||||
if this.reverse {
|
||||
if this.caseInsensitive {
|
||||
return nil, !strings.HasPrefix(strings.ToLower(path), strings.ToLower(this.prefix))
|
||||
} else {
|
||||
return nil, !strings.HasPrefix(path, this.prefix)
|
||||
}
|
||||
} else {
|
||||
if this.caseInsensitive {
|
||||
return nil, strings.HasPrefix(strings.ToLower(path), strings.ToLower(this.prefix))
|
||||
} else {
|
||||
return nil, strings.HasPrefix(path, this.prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if this.patternType == HTTPLocationPatternTypeExact {
|
||||
if this.reverse {
|
||||
if this.caseInsensitive {
|
||||
return nil, strings.ToLower(path) != strings.ToLower(this.path)
|
||||
} else {
|
||||
return nil, path != this.path
|
||||
}
|
||||
} else {
|
||||
if this.caseInsensitive {
|
||||
return nil, strings.ToLower(path) == strings.ToLower(this.path)
|
||||
} else {
|
||||
return nil, path == this.path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 正则表达式匹配会让请求延迟0.01-0.02ms,可以使用缓存加速正则匹配,因为大部分路径都是不变的
|
||||
if this.patternType == HTTPLocationPatternTypeRegexp {
|
||||
if this.reg != nil {
|
||||
if this.reverse {
|
||||
return nil, !this.reg.MatchString(path)
|
||||
} else {
|
||||
b := this.reg.MatchString(path)
|
||||
if b {
|
||||
result := map[string]string{}
|
||||
matches := this.reg.FindStringSubmatch(path)
|
||||
subNames := this.reg.SubexpNames()
|
||||
for index, value := range matches {
|
||||
result[strconv.Itoa(index)] = value
|
||||
subName := subNames[index]
|
||||
if len(subName) > 0 {
|
||||
result[subName] = value
|
||||
}
|
||||
}
|
||||
return result, true
|
||||
}
|
||||
return nil, b
|
||||
}
|
||||
}
|
||||
|
||||
return nil, this.reverse
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
17
pkg/serverconfigs/http_location_config_test.go
Normal file
17
pkg/serverconfigs/http_location_config_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHTTPLocationConfig_Match_Reg(t *testing.T) {
|
||||
randString := "1024"
|
||||
reg := regexp.MustCompile(`(?P<num>\d+)`)
|
||||
before := time.Now()
|
||||
subNames := reg.SubexpNames()
|
||||
match := reg.FindStringSubmatch(randString)
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
t.Log(subNames[1], "=", match[1])
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
package serverconfigs
|
||||
|
||||
// 跳转到HTTPS配置
|
||||
// TODO 支持跳转的状态码选择
|
||||
type HTTPRedirectToHTTPSConfig struct {
|
||||
IsPrior bool `yaml:"isPrior" json:"isPrior"` // 是否覆盖
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
IsPrior bool `yaml:"isPrior" json:"isPrior"` // 是否覆盖
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
Status int `yaml:"status" json:"status"` // 跳转用的状态码
|
||||
Host string `yaml:"host" json:"host"` // 跳转后的Host
|
||||
Port int `yaml:"port" json:"port"` // 跳转后的端口
|
||||
}
|
||||
|
||||
func (this *HTTPRedirectToHTTPSConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
18
pkg/serverconfigs/http_shutdown_config.go
Normal file
18
pkg/serverconfigs/http_shutdown_config.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package serverconfigs
|
||||
|
||||
// 关闭页面配置
|
||||
type HTTPShutdownConfig struct {
|
||||
IsPrior bool `yaml:"isPrior" json:"isPrior"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
URL string `yaml:"url" json:"url"`
|
||||
Status int `yaml:"status" json:"status"`
|
||||
|
||||
// TODO 可以自定义文本
|
||||
// TODO 可以自定义Content-Type
|
||||
// TODO 可以设置是否立即断开与客户端的连接
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPShutdownConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package serverconfigs
|
||||
|
||||
// 关闭页面配置
|
||||
type HTTPShutdownConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
URL string `yaml:"url" json:"url"`
|
||||
Status int `yaml:"status" json:"status"`
|
||||
}
|
||||
|
||||
// 获取新对象
|
||||
func NewHTTPShutdownConfig() *HTTPShutdownConfig {
|
||||
return &HTTPShutdownConfig{}
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPShutdownConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
@@ -27,9 +27,156 @@ type HTTPWebConfig struct {
|
||||
RequestHeaderPolicy *shared.HTTPHeaderPolicy `yaml:"requestHeaderPolicy" json:"requestHeaderPolicy"` // 请求Header策略
|
||||
ResponseHeaderPolicyRef *shared.HTTPHeaderPolicyRef `yaml:"responseHeaderPolicyRef" json:"responseHeaderPolicyRef"` // 响应Header`
|
||||
ResponseHeaderPolicy *shared.HTTPHeaderPolicy `yaml:"responseHeaderPolicy" json:"responseHeaderPolicy"` // 响应Header策略
|
||||
|
||||
FilterRefs []*HTTPFilterRef `yaml:"filterRefs" json:"filterRefs"` // 筛选配置 TODO
|
||||
FilterPolicies []*HTTPFilterPolicy `yaml:"filterPolicies" json:"filterPolicies"` // 筛选策略
|
||||
}
|
||||
|
||||
func (this *HTTPWebConfig) Init() error {
|
||||
// 路径规则
|
||||
if len(this.Locations) > 0 {
|
||||
for _, location := range this.Locations {
|
||||
err := location.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gzip
|
||||
if this.Gzip != nil {
|
||||
err := this.Gzip.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// charset
|
||||
if this.Charset != nil {
|
||||
err := this.Charset.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// shutdown
|
||||
if this.Shutdown != nil {
|
||||
err := this.Shutdown.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// pages
|
||||
if len(this.Pages) > 0 {
|
||||
for _, page := range this.Pages {
|
||||
err := page.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// redirectToHTTPS
|
||||
if this.RedirectToHttps != nil {
|
||||
err := this.RedirectToHttps.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// accessLog
|
||||
if this.AccessLogRef != nil {
|
||||
err := this.AccessLogRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// stat
|
||||
if this.StatRef != nil {
|
||||
err := this.StatRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// cache
|
||||
if this.CacheRef != nil {
|
||||
err := this.CacheRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// firewall
|
||||
if this.FirewallRef != nil {
|
||||
err := this.FirewallRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// websocket
|
||||
if this.WebsocketRef != nil {
|
||||
err := this.WebsocketRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if this.Websocket != nil {
|
||||
err := this.Websocket.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// request header
|
||||
if this.RequestHeaderPolicyRef != nil {
|
||||
err := this.RequestHeaderPolicyRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if this.RequestHeaderPolicy != nil {
|
||||
err := this.RequestHeaderPolicy.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// response header
|
||||
if this.ResponseHeaderPolicyRef != nil {
|
||||
err := this.ResponseHeaderPolicyRef.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if this.ResponseHeaderPolicy != nil {
|
||||
err := this.ResponseHeaderPolicy.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// filters
|
||||
if this.FilterRefs != nil {
|
||||
for _, ref := range this.FilterRefs {
|
||||
err := ref.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if this.FilterPolicies != nil {
|
||||
for _, policy := range this.FilterPolicies {
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"time"
|
||||
|
||||
@@ -5,3 +5,7 @@ type HTTPWebsocketRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
WebsocketId int64 `yaml:"websocketId" json:"websocketId"`
|
||||
}
|
||||
|
||||
func (this *HTTPWebsocketRef) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ type OriginConfig struct {
|
||||
RequestURI string `yaml:"requestURI" json:"requestURI"` // 转发后的请求URI TODO
|
||||
Host string `yaml:"host" json:"host"` // 自定义主机名 TODO
|
||||
|
||||
RequestHeaders *shared.HTTPHeaderPolicy `yaml:"requestHeaders" json:"requestHeaders"` // 请求Header设置 TODO
|
||||
ResponseHeaders *shared.HTTPHeaderPolicy `yaml:"responseHeaders" json:"responseHeaders"`
|
||||
RequestHeaderPolicyRef *shared.HTTPHeaderPolicyRef `yaml:"requestHeaderPolicyRef" json:"requestHeaderPolicyRef"` // 请求Header
|
||||
RequestHeaderPolicy *shared.HTTPHeaderPolicy `yaml:"requestHeaderPolicy" json:"requestHeaderPolicy"` // 请求Header策略
|
||||
ResponseHeaderPolicyRef *shared.HTTPHeaderPolicyRef `yaml:"responseHeaderPolicyRef" json:"responseHeaderPolicyRef"` // 响应Header`
|
||||
ResponseHeaderPolicy *shared.HTTPHeaderPolicy `yaml:"responseHeaderPolicy" json:"responseHeaderPolicy"` // 响应Header策略
|
||||
|
||||
// 健康检查URL,目前支持:
|
||||
// - http|https 返回2xx-3xx认为成功
|
||||
@@ -61,6 +63,8 @@ type OriginConfig struct {
|
||||
uniqueKey string
|
||||
|
||||
hasAddrVariables bool // 地址中是否含有变量
|
||||
|
||||
realAddr string // 最终的Addr TODO
|
||||
}
|
||||
|
||||
// 校验
|
||||
@@ -77,23 +81,29 @@ func (this *OriginConfig) Init() error {
|
||||
this.uniqueKey = strconv.FormatInt(this.Id, 10) + "@" + fmt.Sprintf("%d", this.Version)
|
||||
|
||||
// failTimeout
|
||||
this.connTimeoutDuration = this.ConnTimeout.Duration()
|
||||
if this.ConnTimeout != nil {
|
||||
this.connTimeoutDuration = this.ConnTimeout.Duration()
|
||||
}
|
||||
|
||||
// readTimeout
|
||||
this.readTimeoutDuration = this.ReadTimeout.Duration()
|
||||
if this.ReadTimeout != nil {
|
||||
this.readTimeoutDuration = this.ReadTimeout.Duration()
|
||||
}
|
||||
|
||||
// idleTimeout
|
||||
this.idleTimeoutDuration = this.IdleTimeout.Duration()
|
||||
if this.IdleTimeout != nil {
|
||||
this.idleTimeoutDuration = this.IdleTimeout.Duration()
|
||||
}
|
||||
|
||||
// Headers
|
||||
if this.RequestHeaders != nil {
|
||||
err := this.RequestHeaders.Init()
|
||||
if this.RequestHeaderPolicy != nil {
|
||||
err := this.RequestHeaderPolicy.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if this.ResponseHeaders != nil {
|
||||
err := this.ResponseHeaders.Init()
|
||||
if this.ResponseHeaderPolicy != nil {
|
||||
err := this.ResponseHeaderPolicy.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -116,10 +126,6 @@ func (this *OriginConfig) Init() error {
|
||||
|
||||
// TODO init health check
|
||||
|
||||
// headers
|
||||
this.hasRequestHeaders = this.RequestHeaders != nil && !this.RequestHeaders.IsEmpty()
|
||||
this.hasRequestHeaders = this.ResponseHeaders != nil && !this.ResponseHeaders.IsEmpty()
|
||||
|
||||
// host
|
||||
this.hasHost = len(this.Host) > 0
|
||||
|
||||
@@ -168,3 +174,13 @@ func (this *OriginConfig) Connect() (net.Conn, error) {
|
||||
|
||||
return nil, errors.New("invalid scheme '" + this.Addr.Protocol.String() + "'")
|
||||
}
|
||||
|
||||
// 获取最终请求的地址
|
||||
func (this *OriginConfig) RealAddr() string {
|
||||
return this.realAddr
|
||||
}
|
||||
|
||||
// 设置最终请求的地址 TODO 需要实现
|
||||
func (this *OriginConfig) SetRealAddr(realAddr string) {
|
||||
this.realAddr = realAddr
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ type ServerConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
Type string `yaml:"type" json:"type"` // 类型
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
Components []*ComponentConfig `yaml:"components" json:"components"` // 组件
|
||||
Filters []*FilterConfig `yaml:"filters" json:"filters"` // 过滤器
|
||||
Name string `yaml:"name" json:"name"` // 名称
|
||||
Description string `yaml:"description" json:"description"` // 描述
|
||||
ServerNames []*ServerNameConfig `yaml:"serverNames" json:"serverNames"` // 域名
|
||||
@@ -93,6 +91,13 @@ func (this *ServerConfig) Init() error {
|
||||
}
|
||||
}
|
||||
|
||||
if this.Web != nil {
|
||||
err := this.Web.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package serverconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
|
||||
type ServerNameType = string
|
||||
|
||||
|
||||
@@ -5,3 +5,7 @@ type HTTPHeaderPolicyRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
HeaderPolicyId int64 `yaml:"headerPolicyId" json:"headerPolicyId"`
|
||||
}
|
||||
|
||||
func (this *HTTPHeaderPolicyRef) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
7
pkg/serverconfigs/shared/http_header_ref.go
Normal file
7
pkg/serverconfigs/shared/http_header_ref.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package shared
|
||||
|
||||
// Header引用
|
||||
type HTTPHeaderRef struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
HeaderId int64 `yaml:"headerId" json:"headerId"`
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package shared
|
||||
|
||||
// HeaderList定义
|
||||
type HTTPHeaderPolicy struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
Name string `yaml:"name" json:"name"` // 名称 TODO
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 TODO
|
||||
Description string `yaml:"description" json:"description"` // 描述 TODO
|
||||
|
||||
AddHeaders []*HTTPHeaderConfig `yaml:"addHeaders" json:"addHeaders"` // TODO
|
||||
AddTrailers []*HTTPHeaderConfig `yaml:"addTrailers" json:"addTrailers"` // TODO
|
||||
SetHeaders []*HTTPHeaderConfig `yaml:"setHeaders" json:"setHeaders"` // TODO
|
||||
ReplaceHeaders []*HTTPHeaderConfig `yaml:"replaceHeaders" json:"replaceHeaders"` // 替换Header内容 TODO
|
||||
DeletedHeaders []string `yaml:"deleteHeaders" json:"deleteHeaders"` // 删除的Header TODO
|
||||
|
||||
Expires *HTTPExpireHeaderConfig `yaml:"expires" json:"expires"` // TODO
|
||||
}
|
||||
|
||||
// 获取新对象
|
||||
func NewHTTPHeaderPolicy() *HTTPHeaderPolicy {
|
||||
return &HTTPHeaderPolicy{}
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPHeaderPolicy) Init() error {
|
||||
for _, h := range this.AddHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.AddTrailers {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.SetHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.ReplaceHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断是否为空
|
||||
func (this *HTTPHeaderPolicy) IsEmpty() bool {
|
||||
return len(this.AddHeaders) == 0 && len(this.AddTrailers) == 0 && len(this.SetHeaders) == 0 && len(this.ReplaceHeaders) == 0 && this.Expires == nil
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHeaderList_FormatHeaders(t *testing.T) {
|
||||
list := NewHTTPHeaderPolicy()
|
||||
err := list.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
75
pkg/serverconfigs/shared/http_headers_policy.go
Normal file
75
pkg/serverconfigs/shared/http_headers_policy.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package shared
|
||||
|
||||
import "strings"
|
||||
|
||||
// HeaderList定义
|
||||
type HTTPHeaderPolicy struct {
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
Name string `yaml:"name" json:"name"` // 名称 TODO
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 TODO
|
||||
Description string `yaml:"description" json:"description"` // 描述 TODO
|
||||
|
||||
AddHeaderRefs []*HTTPHeaderRef `yaml:"addHeaderRefs" json:"addHeaderRefs"`
|
||||
AddHeaders []*HTTPHeaderConfig `yaml:"addHeaders" json:"addHeaders"`
|
||||
AddTrailerRefs []*HTTPHeaderRef `yaml:"addTrailerRefs" json:"addTrailerRefs"`
|
||||
AddTrailers []*HTTPHeaderConfig `yaml:"addTrailers" json:"addTrailers"` // TODO
|
||||
SetHeaderRefs []*HTTPHeaderRef `yaml:"setHeaderRefs" json:"setHeaderRefs"`
|
||||
SetHeaders []*HTTPHeaderConfig `yaml:"setHeaders" json:"setHeaders"`
|
||||
ReplaceHeaderRefs []*HTTPHeaderRef `yaml:"replaceHeaderRefs" json:"replaceHeaderRefs"`
|
||||
ReplaceHeaders []*HTTPHeaderConfig `yaml:"replaceHeaders" json:"replaceHeaders"` // 替换Header内容 TODO
|
||||
DeleteHeaders []string `yaml:"deleteHeaders" json:"deleteHeaders"` // 删除的Header
|
||||
|
||||
Expires *HTTPExpireHeaderConfig `yaml:"expires" json:"expires"` // TODO
|
||||
|
||||
deleteHeaderMap map[string]bool // header => bool
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (this *HTTPHeaderPolicy) Init() error {
|
||||
for _, h := range this.AddHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.AddTrailers {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.SetHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range this.ReplaceHeaders {
|
||||
err := h.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// delete
|
||||
this.deleteHeaderMap = map[string]bool{}
|
||||
for _, header := range this.DeleteHeaders {
|
||||
this.deleteHeaderMap[strings.ToUpper(header)] = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断是否为空
|
||||
func (this *HTTPHeaderPolicy) IsEmpty() bool {
|
||||
return len(this.AddHeaders) == 0 && len(this.AddTrailers) == 0 && len(this.SetHeaders) == 0 && len(this.ReplaceHeaders) == 0 && this.Expires == nil
|
||||
}
|
||||
|
||||
// 判断删除列表中是否包含某个Header
|
||||
func (this *HTTPHeaderPolicy) ContainsDeletedHeader(header string) bool {
|
||||
_, ok := this.deleteHeaderMap[strings.ToUpper(header)]
|
||||
return ok
|
||||
}
|
||||
57
pkg/serverconfigs/shared/http_headers_policy_test.go
Normal file
57
pkg/serverconfigs/shared/http_headers_policy_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPHeaderPolicy_FormatHeaders(t *testing.T) {
|
||||
policy := &HTTPHeaderPolicy{}
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPHeaderPolicy_ShouldDeleteHeader(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
policy := &HTTPHeaderPolicy{}
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsFalse(policy.ContainsDeletedHeader("Origin"))
|
||||
}
|
||||
{
|
||||
policy := &HTTPHeaderPolicy{
|
||||
DeleteHeaders: []string{"Hello", "World"},
|
||||
}
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsFalse(policy.ContainsDeletedHeader("Origin"))
|
||||
}
|
||||
{
|
||||
policy := &HTTPHeaderPolicy{
|
||||
DeleteHeaders: []string{"origin"},
|
||||
}
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(policy.ContainsDeletedHeader("Origin"))
|
||||
}
|
||||
{
|
||||
policy := &HTTPHeaderPolicy{
|
||||
DeleteHeaders: []string{"Origin"},
|
||||
}
|
||||
err := policy.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.IsTrue(policy.ContainsDeletedHeader("Origin"))
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,9 @@ import (
|
||||
)
|
||||
|
||||
// 重写条件定义
|
||||
type RequestCond struct {
|
||||
Id string `yaml:"id" json:"id"` // ID
|
||||
type HTTPRequestCond struct {
|
||||
Id string `yaml:"id" json:"id"` // ID
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
|
||||
// 要测试的字符串
|
||||
// 其中可以使用跟请求相关的参数,比如:
|
||||
@@ -41,15 +42,8 @@ type RequestCond struct {
|
||||
arrayValue []string
|
||||
}
|
||||
|
||||
// 取得新对象
|
||||
func NewRequestCond() *RequestCond {
|
||||
return &RequestCond{
|
||||
Id: stringutil.Rand(16),
|
||||
}
|
||||
}
|
||||
|
||||
// 校验配置
|
||||
func (this *RequestCond) Init() error {
|
||||
func (this *HTTPRequestCond) Init() error {
|
||||
this.isInt = RegexpDigitNumber.MatchString(this.Value)
|
||||
this.isFloat = RegexpFloatNumber.MatchString(this.Value)
|
||||
|
||||
@@ -144,7 +138,7 @@ func (this *RequestCond) Init() error {
|
||||
}
|
||||
|
||||
// 将此条件应用于请求,检查是否匹配
|
||||
func (this *RequestCond) Match(formatter func(source string) string) bool {
|
||||
func (this *HTTPRequestCond) Match(formatter func(source string) string) bool {
|
||||
paramValue := formatter(this.Param)
|
||||
switch this.Operator {
|
||||
case RequestCondOperatorRegexp:
|
||||
@@ -361,7 +355,7 @@ func (this *RequestCond) Match(formatter func(source string) string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *RequestCond) ipToInt64(ip net.IP) int64 {
|
||||
func (this *HTTPRequestCond) ipToInt64(ip net.IP) int64 {
|
||||
if len(ip) == 0 {
|
||||
return 0
|
||||
}
|
||||
38
pkg/serverconfigs/shared/http_request_cond_group.go
Normal file
38
pkg/serverconfigs/shared/http_request_cond_group.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package shared
|
||||
|
||||
// 请求条件分组
|
||||
type HTTPRequestCondGroup struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Connector string `yaml:"connector" json:"connector"` // 条件之间的关系
|
||||
Conds []*HTTPRequestCond `yaml:"conds" json:"conds"` // 条件列表
|
||||
IsReverse bool `yaml:"isReverse" json:"isReverse"` // 是否反向匹配
|
||||
}
|
||||
|
||||
// 初始化
|
||||
func (this *HTTPRequestCondGroup) Init() error {
|
||||
if len(this.Conds) > 0 {
|
||||
for _, cond := range this.Conds {
|
||||
err := cond.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *HTTPRequestCondGroup) Match(formatter func(source string) string) bool {
|
||||
if !this.IsOn {
|
||||
return !this.IsReverse
|
||||
}
|
||||
for _, cond := range this.Conds {
|
||||
isMatched := cond.Match(formatter)
|
||||
if this.Connector == "or" && isMatched {
|
||||
return !this.IsReverse
|
||||
}
|
||||
if this.Connector == "and" && !isMatched {
|
||||
return this.IsReverse
|
||||
}
|
||||
}
|
||||
return !this.IsReverse
|
||||
}
|
||||
@@ -14,7 +14,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello",
|
||||
Operator: RequestCondOperatorRegexp,
|
||||
Value: "abc",
|
||||
@@ -26,7 +26,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello",
|
||||
Operator: RequestCondOperatorRegexp,
|
||||
Value: "/\\w+",
|
||||
@@ -38,7 +38,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/article/123.html",
|
||||
Operator: RequestCondOperatorRegexp,
|
||||
Value: `^/article/\d+\.html$`,
|
||||
@@ -50,7 +50,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello",
|
||||
Operator: RequestCondOperatorRegexp,
|
||||
Value: "[",
|
||||
@@ -62,7 +62,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello",
|
||||
Operator: RequestCondOperatorNotRegexp,
|
||||
Value: "abc",
|
||||
@@ -74,7 +74,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello",
|
||||
Operator: RequestCondOperatorNotRegexp,
|
||||
Value: "/\\w+",
|
||||
@@ -86,7 +86,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123.123",
|
||||
Operator: RequestCondOperatorEqInt,
|
||||
Value: "123",
|
||||
@@ -98,7 +98,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123",
|
||||
Operator: RequestCondOperatorEqInt,
|
||||
Value: "123",
|
||||
@@ -110,7 +110,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "abc",
|
||||
Operator: RequestCondOperatorEqInt,
|
||||
Value: "abc",
|
||||
@@ -122,7 +122,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123",
|
||||
Operator: RequestCondOperatorEqFloat,
|
||||
Value: "123",
|
||||
@@ -134,7 +134,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123.0",
|
||||
Operator: RequestCondOperatorEqFloat,
|
||||
Value: "123",
|
||||
@@ -146,7 +146,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123.123",
|
||||
Operator: RequestCondOperatorEqFloat,
|
||||
Value: "123.12",
|
||||
@@ -158,7 +158,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123",
|
||||
Operator: RequestCondOperatorGtFloat,
|
||||
Value: "1",
|
||||
@@ -170,7 +170,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "123",
|
||||
Operator: RequestCondOperatorGtFloat,
|
||||
Value: "125",
|
||||
@@ -182,7 +182,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorGteFloat,
|
||||
Value: "125",
|
||||
@@ -194,7 +194,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorLtFloat,
|
||||
Value: "127",
|
||||
@@ -206,7 +206,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorLteFloat,
|
||||
Value: "127",
|
||||
@@ -218,7 +218,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorEqString,
|
||||
Value: "125",
|
||||
@@ -230,7 +230,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorNeqString,
|
||||
Value: "125",
|
||||
@@ -242,7 +242,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "125",
|
||||
Operator: RequestCondOperatorNeqString,
|
||||
Value: "127",
|
||||
@@ -254,7 +254,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorHasPrefix,
|
||||
Value: "/hello",
|
||||
@@ -266,7 +266,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorHasPrefix,
|
||||
Value: "/hello2",
|
||||
@@ -278,7 +278,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorHasSuffix,
|
||||
Value: "world",
|
||||
@@ -290,7 +290,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorHasSuffix,
|
||||
Value: "world/",
|
||||
@@ -302,7 +302,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorContainsString,
|
||||
Value: "wo",
|
||||
@@ -314,7 +314,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorContainsString,
|
||||
Value: "wr",
|
||||
@@ -326,7 +326,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorNotContainsString,
|
||||
Value: "HELLO",
|
||||
@@ -338,7 +338,7 @@ func TestRequestCond_Compare1(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "/hello/world",
|
||||
Operator: RequestCondOperatorNotContainsString,
|
||||
Value: "hello",
|
||||
@@ -354,7 +354,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "hello",
|
||||
Operator: RequestCondOperatorEqIP,
|
||||
Value: "hello",
|
||||
@@ -366,7 +366,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorEqIP,
|
||||
Value: "hello",
|
||||
@@ -378,7 +378,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorEqIP,
|
||||
Value: "192.168.1.100",
|
||||
@@ -390,7 +390,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorGtIP,
|
||||
Value: "192.168.1.90",
|
||||
@@ -402,7 +402,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorGteIP,
|
||||
Value: "192.168.1.90",
|
||||
@@ -414,7 +414,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.80",
|
||||
Operator: RequestCondOperatorLtIP,
|
||||
Value: "192.168.1.90",
|
||||
@@ -426,7 +426,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.0.100",
|
||||
Operator: RequestCondOperatorLteIP,
|
||||
Value: "192.168.1.90",
|
||||
@@ -438,7 +438,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.0.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "192.168.0.90,",
|
||||
@@ -450,7 +450,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.0.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "192.168.0.90,192.168.1.100",
|
||||
@@ -462,7 +462,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.0.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: ",192.168.1.100",
|
||||
@@ -474,7 +474,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "192.168.0.90,192.168.1.99",
|
||||
@@ -486,7 +486,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "192.168.0.90/24",
|
||||
@@ -498,7 +498,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "192.168.0.90/18",
|
||||
@@ -510,7 +510,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPRange,
|
||||
Value: "a/18",
|
||||
@@ -522,7 +522,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPMod10,
|
||||
Value: "6",
|
||||
@@ -534,7 +534,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPMod100,
|
||||
Value: "76",
|
||||
@@ -546,7 +546,7 @@ func TestRequestCond_IP(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "192.168.1.100",
|
||||
Operator: RequestCondOperatorIPMod,
|
||||
Value: "10,6",
|
||||
@@ -585,7 +585,7 @@ func TestRequestCondIPCompare(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{}
|
||||
cond := HTTPRequestCond{}
|
||||
t.Log(cond.ipToInt64(net.ParseIP("192.168.1.100")))
|
||||
t.Log(cond.ipToInt64(net.ParseIP("192.168.1.99")))
|
||||
t.Log(cond.ipToInt64(net.ParseIP("0.0.0.0")))
|
||||
@@ -600,7 +600,7 @@ func TestRequestCond_In(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a",
|
||||
Operator: RequestCondOperatorIn,
|
||||
Value: `a`,
|
||||
@@ -612,7 +612,7 @@ func TestRequestCond_In(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a",
|
||||
Operator: RequestCondOperatorIn,
|
||||
Value: `["a", "b"]`,
|
||||
@@ -624,7 +624,7 @@ func TestRequestCond_In(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "c",
|
||||
Operator: RequestCondOperatorNotIn,
|
||||
Value: `["a", "b"]`,
|
||||
@@ -636,7 +636,7 @@ func TestRequestCond_In(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a",
|
||||
Operator: RequestCondOperatorNotIn,
|
||||
Value: `["a", "b"]`,
|
||||
@@ -652,7 +652,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a",
|
||||
Operator: RequestCondOperatorFileExt,
|
||||
Value: `["jpeg", "jpg", "png"]`,
|
||||
@@ -664,7 +664,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a.gif",
|
||||
Operator: RequestCondOperatorFileExt,
|
||||
Value: `["jpeg", "jpg", "png"]`,
|
||||
@@ -676,7 +676,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a.png",
|
||||
Operator: RequestCondOperatorFileExt,
|
||||
Value: `["jpeg", "jpg", "png"]`,
|
||||
@@ -688,7 +688,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a.png",
|
||||
Operator: RequestCondOperatorFileExist,
|
||||
}
|
||||
@@ -699,7 +699,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: Tea.Root + "/README.md",
|
||||
Operator: RequestCondOperatorFileExist,
|
||||
}
|
||||
@@ -710,7 +710,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: Tea.Root + "/README.md?v=1",
|
||||
Operator: RequestCondOperatorFileExist,
|
||||
}
|
||||
@@ -721,7 +721,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: Tea.Root,
|
||||
Operator: RequestCondOperatorFileExist,
|
||||
}
|
||||
@@ -732,7 +732,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: Tea.Root,
|
||||
Operator: RequestCondOperatorFileExist,
|
||||
}
|
||||
@@ -743,7 +743,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "a.png",
|
||||
Operator: RequestCondOperatorFileNotExist,
|
||||
}
|
||||
@@ -754,7 +754,7 @@ func TestRequestCond_File(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: Tea.Root + "/README.md",
|
||||
Operator: RequestCondOperatorFileNotExist,
|
||||
}
|
||||
@@ -769,7 +769,7 @@ func TestRequestCond_MimeType(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "text/html; charset=utf-8",
|
||||
Operator: RequestCondOperatorFileMimeType,
|
||||
Value: `["text/html"]`,
|
||||
@@ -781,7 +781,7 @@ func TestRequestCond_MimeType(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "text/html; charset=utf-8",
|
||||
Operator: RequestCondOperatorFileMimeType,
|
||||
Value: `["text/*"]`,
|
||||
@@ -793,7 +793,7 @@ func TestRequestCond_MimeType(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "text/html; charset=utf-8",
|
||||
Operator: RequestCondOperatorFileMimeType,
|
||||
Value: `["image/*"]`,
|
||||
@@ -805,7 +805,7 @@ func TestRequestCond_MimeType(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "text/plain; charset=utf-8",
|
||||
Operator: RequestCondOperatorFileMimeType,
|
||||
Value: `["text/html", "image/jpeg", "image/png"]`,
|
||||
@@ -821,7 +821,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1.0",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `1.0,1.1`,
|
||||
@@ -833,7 +833,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1.0",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `1.0,`,
|
||||
@@ -845,7 +845,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1.0",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `,1.1`,
|
||||
@@ -857,7 +857,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "0.9",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `1.0,1.1`,
|
||||
@@ -869,7 +869,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "0.9",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `1.0`,
|
||||
@@ -881,7 +881,7 @@ func TestRequestCond_Version(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1.1",
|
||||
Operator: RequestCondOperatorVersionRange,
|
||||
Value: `1.0`,
|
||||
@@ -903,7 +903,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "1",
|
||||
@@ -915,7 +915,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "2",
|
||||
@@ -927,7 +927,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "3",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "3",
|
||||
@@ -939,7 +939,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "1",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "11,1",
|
||||
@@ -951,7 +951,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "3",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "11,3",
|
||||
@@ -963,7 +963,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: "4",
|
||||
Operator: RequestCondOperatorMod,
|
||||
Value: "2,0",
|
||||
@@ -975,7 +975,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: fmt.Sprintf("%d", i),
|
||||
Operator: RequestCondOperatorMod10,
|
||||
Value: fmt.Sprintf("%d", i%10),
|
||||
@@ -987,7 +987,7 @@ func TestRequestCond_Mod(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := 0; i < 2000; i++ {
|
||||
cond := RequestCond{
|
||||
cond := HTTPRequestCond{
|
||||
Param: fmt.Sprintf("%d", i),
|
||||
Operator: RequestCondOperatorMod100,
|
||||
Value: fmt.Sprintf("%d", i%100),
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package sslconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user