mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	HTTP Header:实现请求方法、域名、状态码等限制,实现内容替换功能
This commit is contained in:
		@@ -2,7 +2,7 @@ package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
	"github.com/iwind/TeaGo/Tea"
 | 
			
		||||
@@ -80,22 +80,69 @@ func (this *HTTPHeaderDAO) FindHTTPHeaderName(tx *dbs.Tx, id int64) (string, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.UserId = userId
 | 
			
		||||
	op.State = HTTPHeaderStateEnabled
 | 
			
		||||
	op.IsOn = true
 | 
			
		||||
	op.Name = name
 | 
			
		||||
	op.Value = value
 | 
			
		||||
 | 
			
		||||
	statusConfig := &shared.HTTPStatusConfig{
 | 
			
		||||
	// 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 0, 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 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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
@@ -104,7 +151,7 @@ func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, name string, value string) (
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		return errors.New("invalid headerId")
 | 
			
		||||
	}
 | 
			
		||||
@@ -113,7 +160,63 @@ func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string,
 | 
			
		||||
	op.Id = headerId
 | 
			
		||||
	op.Name = name
 | 
			
		||||
	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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -136,7 +239,21 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
 | 
			
		||||
	config.IsOn = header.IsOn == 1
 | 
			
		||||
	config.Name = header.Name
 | 
			
		||||
	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 {
 | 
			
		||||
		status := &shared.HTTPStatusConfig{}
 | 
			
		||||
		err = json.Unmarshal([]byte(header.Status), status)
 | 
			
		||||
@@ -146,6 +263,26 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
// HTTP Header
 | 
			
		||||
// HTTPHeader HTTP Header
 | 
			
		||||
type HTTPHeader struct {
 | 
			
		||||
	Id              uint32 `field:"id"`              // ID
 | 
			
		||||
	AdminId         uint32 `field:"adminId"`         // 管理员ID
 | 
			
		||||
@@ -11,6 +11,12 @@ type HTTPHeader struct {
 | 
			
		||||
	Value           string `field:"value"`           // 值
 | 
			
		||||
	Order           uint32 `field:"order"`           // 排序
 | 
			
		||||
	Status          string `field:"status"`          // 状态码设置
 | 
			
		||||
	DisableRedirect uint8  `field:"disableRedirect"` // 是否不支持跳转
 | 
			
		||||
	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"`       // 创建时间
 | 
			
		||||
}
 | 
			
		||||
@@ -25,6 +31,12 @@ type HTTPHeaderOperator struct {
 | 
			
		||||
	Value           interface{} // 值
 | 
			
		||||
	Order           interface{} // 排序
 | 
			
		||||
	Status          interface{} // 状态码设置
 | 
			
		||||
	DisableRedirect interface{} // 是否不支持跳转
 | 
			
		||||
	ShouldAppend    interface{} // 是否为附加
 | 
			
		||||
	ShouldReplace   interface{} // 是否替换变量
 | 
			
		||||
	ReplaceValues   interface{} // 替换的值
 | 
			
		||||
	Methods         interface{} // 支持的方法
 | 
			
		||||
	Domains         interface{} // 支持的域名
 | 
			
		||||
	State           interface{} // 状态
 | 
			
		||||
	CreatedAt       interface{} // 创建时间
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -186,48 +186,6 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
 | 
			
		||||
	config.Id = int64(policy.Id)
 | 
			
		||||
	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
 | 
			
		||||
	if len(policy.SetHeaders) > 0 {
 | 
			
		||||
		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
 | 
			
		||||
	if len(policy.DeleteHeaders) > 0 {
 | 
			
		||||
		headers := []string{}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,16 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"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/serverconfigs/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type HTTPHeaderService struct {
 | 
			
		||||
	BaseService
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 创建Header
 | 
			
		||||
// CreateHTTPHeader 创建Header
 | 
			
		||||
func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.CreateHTTPHeaderRequest) (*pb.CreateHTTPHeaderResponse, error) {
 | 
			
		||||
	// 校验请求
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
 | 
			
		||||
@@ -25,7 +27,22 @@ func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.Cre
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -33,7 +50,7 @@ func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.Cre
 | 
			
		||||
	return &pb.CreateHTTPHeaderResponse{HeaderId: headerId}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改Header
 | 
			
		||||
// UpdateHTTPHeader 修改Header
 | 
			
		||||
func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.UpdateHTTPHeaderRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	// 校验请求
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
 | 
			
		||||
@@ -47,7 +64,22 @@ func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.Upd
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -55,7 +87,7 @@ func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.Upd
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 查找配置
 | 
			
		||||
// FindEnabledHTTPHeaderConfig 查找配置
 | 
			
		||||
func (this *HTTPHeaderService) FindEnabledHTTPHeaderConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderConfigRequest) (*pb.FindEnabledHTTPHeaderConfigResponse, error) {
 | 
			
		||||
	// 校验请求
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Reference in New Issue
	
	Block a user