HTTP Header:实现请求方法、域名、状态码等限制,实现内容替换功能

This commit is contained in:
GoEdgeLab
2021-12-15 09:56:06 +08:00
parent d65c4871f8
commit afe14ebbc3
5 changed files with 216 additions and 101 deletions

View File

@@ -2,7 +2,7 @@ package models
import ( import (
"encoding/json" "encoding/json"
"errors" "github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
@@ -80,22 +80,69 @@ func (this *HTTPHeaderDAO) FindHTTPHeaderName(tx *dbs.Tx, id int64) (string, err
} }
// CreateHeader 创建Header // CreateHeader 创建Header
func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, name string, value string) (int64, error) { func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, userId int64, name string, value string, status []int, disableRedirect bool, shouldAppend bool, shouldReplace bool, replaceValues []*shared.HTTPHeaderReplaceValue, methods []string, domains []string) (int64, error) {
op := NewHTTPHeaderOperator() op := NewHTTPHeaderOperator()
op.UserId = userId
op.State = HTTPHeaderStateEnabled op.State = HTTPHeaderStateEnabled
op.IsOn = true op.IsOn = true
op.Name = name op.Name = name
op.Value = value op.Value = value
statusConfig := &shared.HTTPStatusConfig{ // status
Always: true, var statusConfig *shared.HTTPStatusConfig
if len(status) == 0 {
statusConfig = &shared.HTTPStatusConfig{
Always: true,
}
} else {
statusConfig = &shared.HTTPStatusConfig{
Always: false,
Codes: status,
}
} }
statusJSON, err := json.Marshal(statusConfig) statusJSON, err := json.Marshal(statusConfig)
if err != nil { if err != nil {
return 0, err return 0, err
} }
op.Status = statusJSON op.Status = statusJSON
op.DisableRedirect = disableRedirect
op.ShouldAppend = shouldAppend
op.ShouldReplace = shouldReplace
if len(replaceValues) == 0 {
op.ReplaceValues = "[]"
} else {
replaceValuesJSON, err := json.Marshal(replaceValues)
if err != nil {
return 0, err
}
op.ReplaceValues = replaceValuesJSON
}
// methods
if len(methods) == 0 {
op.Methods = "[]"
} else {
methodsJSON, err := json.Marshal(methods)
if err != nil {
return 0, err
}
op.Methods = methodsJSON
}
// domains
if len(domains) == 0 {
op.Domains = "[]"
} else {
domainsJSON, err := json.Marshal(domains)
if err != nil {
return 0, err
}
op.Domains = domainsJSON
}
err = this.Save(tx, op) err = this.Save(tx, op)
if err != nil { if err != nil {
return 0, err return 0, err
@@ -104,7 +151,7 @@ func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, name string, value string) (
} }
// UpdateHeader 修改Header // UpdateHeader 修改Header
func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string, value string) error { func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string, value string, status []int, disableRedirect bool, shouldAppend bool, shouldReplace bool, replaceValues []*shared.HTTPHeaderReplaceValue, methods []string, domains []string) error {
if headerId <= 0 { if headerId <= 0 {
return errors.New("invalid headerId") return errors.New("invalid headerId")
} }
@@ -113,7 +160,63 @@ func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string,
op.Id = headerId op.Id = headerId
op.Name = name op.Name = name
op.Value = value op.Value = value
err := this.Save(tx, op)
// status
var statusConfig *shared.HTTPStatusConfig
if len(status) == 0 {
statusConfig = &shared.HTTPStatusConfig{
Always: true,
}
} else {
statusConfig = &shared.HTTPStatusConfig{
Always: false,
Codes: status,
}
}
statusJSON, err := json.Marshal(statusConfig)
if err != nil {
return err
}
op.Status = statusJSON
op.DisableRedirect = disableRedirect
op.ShouldAppend = shouldAppend
op.ShouldReplace = shouldReplace
if len(replaceValues) == 0 {
op.ReplaceValues = "[]"
} else {
replaceValuesJSON, err := json.Marshal(replaceValues)
if err != nil {
return err
}
op.ReplaceValues = replaceValuesJSON
}
// methods
if len(methods) == 0 {
op.Methods = "[]"
} else {
methodsJSON, err := json.Marshal(methods)
if err != nil {
return err
}
op.Methods = methodsJSON
}
// domains
if len(domains) == 0 {
op.Domains = "[]"
} else {
domainsJSON, err := json.Marshal(domains)
if err != nil {
return err
}
op.Domains = domainsJSON
}
err = this.Save(tx, op)
if err != nil { if err != nil {
return err return err
} }
@@ -136,7 +239,21 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
config.IsOn = header.IsOn == 1 config.IsOn = header.IsOn == 1
config.Name = header.Name config.Name = header.Name
config.Value = header.Value config.Value = header.Value
config.DisableRedirect = header.DisableRedirect == 1
config.ShouldAppend = header.ShouldAppend == 1
// replace
config.ShouldReplace = header.ShouldReplace == 1
if len(header.ReplaceValues) > 0 {
var values = []*shared.HTTPHeaderReplaceValue{}
err = json.Unmarshal([]byte(header.ReplaceValues), &values)
if err != nil {
return nil, err
}
config.ReplaceValues = values
}
// status
if len(header.Status) > 0 { if len(header.Status) > 0 {
status := &shared.HTTPStatusConfig{} status := &shared.HTTPStatusConfig{}
err = json.Unmarshal([]byte(header.Status), status) err = json.Unmarshal([]byte(header.Status), status)
@@ -146,6 +263,26 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
config.Status = status config.Status = status
} }
// methods
if len(header.Methods) > 0 {
var methods = []string{}
err = json.Unmarshal([]byte(header.Methods), &methods)
if err != nil {
return nil, err
}
config.Methods = methods
}
// domains
if len(header.Domains) > 0 {
var domains = []string{}
err = json.Unmarshal([]byte(header.Domains), &domains)
if err != nil {
return nil, err
}
config.Domains = domains
}
return config, nil return config, nil
} }

View File

@@ -1,32 +1,44 @@
package models package models
// HTTP Header // HTTPHeader HTTP Header
type HTTPHeader struct { type HTTPHeader struct {
Id uint32 `field:"id"` // ID Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用 IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称 Name string `field:"name"` // 名称
Value string `field:"value"` // 值 Value string `field:"value"` // 值
Order uint32 `field:"order"` // 排序 Order uint32 `field:"order"` // 排序
Status string `field:"status"` // 状态码设置 Status string `field:"status"` // 状态码设置
State uint8 `field:"state"` // 状态 DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
CreatedAt uint64 `field:"createdAt"` // 创建时间 ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
ReplaceValues string `field:"replaceValues"` // 替换的值
Methods string `field:"methods"` // 支持的方法
Domains string `field:"domains"` // 支持的域名
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
} }
type HTTPHeaderOperator struct { type HTTPHeaderOperator struct {
Id interface{} // ID Id interface{} // ID
AdminId interface{} // 管理员ID AdminId interface{} // 管理员ID
UserId interface{} // 用户ID UserId interface{} // 用户ID
TemplateId interface{} // 模版ID TemplateId interface{} // 模版ID
IsOn interface{} // 是否启用 IsOn interface{} // 是否启用
Name interface{} // 名称 Name interface{} // 名称
Value interface{} // 值 Value interface{} // 值
Order interface{} // 排序 Order interface{} // 排序
Status interface{} // 状态码设置 Status interface{} // 状态码设置
State interface{} // 状态 DisableRedirect interface{} // 是否不支持跳转
CreatedAt interface{} // 创建时间 ShouldAppend interface{} // 是否为附加
ShouldReplace interface{} // 是否替换变量
ReplaceValues interface{} // 替换的值
Methods interface{} // 支持的方法
Domains interface{} // 支持的域名
State interface{} // 状态
CreatedAt interface{} // 创建时间
} }
func NewHTTPHeaderOperator() *HTTPHeaderOperator { func NewHTTPHeaderOperator() *HTTPHeaderOperator {

View File

@@ -186,48 +186,6 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
config.Id = int64(policy.Id) config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1 config.IsOn = policy.IsOn == 1
// AddHeaders
if len(policy.AddHeaders) > 0 {
refs := []*shared.HTTPHeaderRef{}
err = json.Unmarshal([]byte(policy.AddHeaders), &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
for _, ref := range refs {
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
if err != nil {
return nil, err
}
config.AddHeaders = append(config.AddHeaders, headerConfig)
}
}
}
// AddTrailers
if len(policy.AddTrailers) > 0 {
refs := []*shared.HTTPHeaderRef{}
err = json.Unmarshal([]byte(policy.AddTrailers), &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
resultRefs := []*shared.HTTPHeaderRef{}
for _, ref := range refs {
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
if err != nil {
return nil, err
}
if headerConfig == nil {
continue
}
resultRefs = append(resultRefs, ref)
config.AddTrailers = append(config.AddTrailers, headerConfig)
}
config.AddHeaderRefs = resultRefs
}
}
// SetHeaders // SetHeaders
if len(policy.SetHeaders) > 0 { if len(policy.SetHeaders) > 0 {
refs := []*shared.HTTPHeaderRef{} refs := []*shared.HTTPHeaderRef{}
@@ -252,30 +210,6 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
} }
} }
// ReplaceHeaders
if len(policy.ReplaceHeaders) > 0 {
refs := []*shared.HTTPHeaderRef{}
err = json.Unmarshal([]byte(policy.ReplaceHeaders), &refs)
if err != nil {
return nil, err
}
if len(refs) > 0 {
resultRefs := []*shared.HTTPHeaderRef{}
for _, ref := range refs {
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
if err != nil {
return nil, err
}
if headerConfig == nil {
continue
}
resultRefs = append(resultRefs, ref)
config.ReplaceHeaders = append(config.ReplaceHeaders, headerConfig)
}
config.ReplaceHeaderRefs = resultRefs
}
}
// Delete Headers // Delete Headers
if len(policy.DeleteHeaders) > 0 { if len(policy.DeleteHeaders) > 0 {
headers := []string{} headers := []string{}

View File

@@ -4,14 +4,16 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models" "github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
) )
type HTTPHeaderService struct { type HTTPHeaderService struct {
BaseService BaseService
} }
// 创建Header // CreateHTTPHeader 创建Header
func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.CreateHTTPHeaderRequest) (*pb.CreateHTTPHeaderResponse, error) { func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.CreateHTTPHeaderRequest) (*pb.CreateHTTPHeaderResponse, error) {
// 校验请求 // 校验请求
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0) _, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
@@ -25,7 +27,22 @@ func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.Cre
tx := this.NullTx() tx := this.NullTx()
headerId, err := models.SharedHTTPHeaderDAO.CreateHeader(tx, req.Name, req.Value) // status
var newStatus = []int{}
for _, status := range req.Status {
newStatus = append(newStatus, int(status))
}
// replace values
var replaceValues = []*shared.HTTPHeaderReplaceValue{}
if len(req.ReplaceValuesJSON) > 0 {
err = json.Unmarshal(req.ReplaceValuesJSON, &replaceValues)
if err != nil {
return nil, errors.New("decode replace values failed: " + err.Error() + ", json: " + string(req.ReplaceValuesJSON))
}
}
headerId, err := models.SharedHTTPHeaderDAO.CreateHeader(tx, userId, req.Name, req.Value, newStatus, req.DisableRedirect, req.ShouldAppend, req.ShouldReplace, replaceValues, req.Methods, req.Domains)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -33,7 +50,7 @@ func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.Cre
return &pb.CreateHTTPHeaderResponse{HeaderId: headerId}, nil return &pb.CreateHTTPHeaderResponse{HeaderId: headerId}, nil
} }
// 修改Header // UpdateHTTPHeader 修改Header
func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.UpdateHTTPHeaderRequest) (*pb.RPCSuccess, error) { func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.UpdateHTTPHeaderRequest) (*pb.RPCSuccess, error) {
// 校验请求 // 校验请求
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0) _, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
@@ -47,7 +64,22 @@ func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.Upd
tx := this.NullTx() tx := this.NullTx()
err = models.SharedHTTPHeaderDAO.UpdateHeader(tx, req.HeaderId, req.Name, req.Value) // status
var newStatus = []int{}
for _, status := range req.Status {
newStatus = append(newStatus, int(status))
}
// replace values
var replaceValues = []*shared.HTTPHeaderReplaceValue{}
if len(req.ReplaceValuesJSON) > 0 {
err = json.Unmarshal(req.ReplaceValuesJSON, &replaceValues)
if err != nil {
return nil, errors.New("decode replace values failed: " + err.Error())
}
}
err = models.SharedHTTPHeaderDAO.UpdateHeader(tx, req.HeaderId, req.Name, req.Value, newStatus, req.DisableRedirect, req.ShouldAppend, req.ShouldReplace, replaceValues, req.Methods, req.Domains)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -55,7 +87,7 @@ func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.Upd
return this.Success() return this.Success()
} }
// 查找配置 // FindEnabledHTTPHeaderConfig 查找配置
func (this *HTTPHeaderService) FindEnabledHTTPHeaderConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderConfigRequest) (*pb.FindEnabledHTTPHeaderConfigResponse, error) { func (this *HTTPHeaderService) FindEnabledHTTPHeaderConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderConfigRequest) (*pb.FindEnabledHTTPHeaderConfigResponse, error) {
// 校验请求 // 校验请求
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0) _, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)

File diff suppressed because one or more lines are too long