Ver Fonte

添加响应头配置功能

新增了响应头配置相关的代码,包括设置、添加和删除响应头的功能,并在服务器核心中实现了响应头的写入。同时调整了部分文件名和结构以保持一致性。
SongZihuan há 3 meses atrás
pai
commit
e3d1dc7cb2

+ 45 - 3
src/config/rules/action/api/api.go

@@ -14,9 +14,9 @@ type RuleAPIConfig struct {
 	AddPath   string                `yaml:"addpath"`
 	SubPath   string                `yaml:"subpath"`
 	Rewrite   rewrite.RewriteConfig `yaml:"rewrite"`
-	HeaderSet []*HeaderConfig       `yaml:"headerset"`
-	HeaderAdd []*HeaderConfig       `yaml:"headeradd"`
-	HeaderDel []*HeaderDelConfig    `yaml:"headerdel"`
+	HeaderSet []*ReqHeaderConfig    `yaml:"headerset"`
+	HeaderAdd []*ReqHeaderConfig    `yaml:"headeradd"`
+	HeaderDel []*ReqHeaderDelConfig `yaml:"headerdel"`
 	QuerySet  []*QueryConfig        `yaml:"queryset"`
 	QueryAdd  []*QueryConfig        `yaml:"queryadd"`
 	QueryDel  []*QueryDelConfig     `yaml:"querydel"`
@@ -94,5 +94,47 @@ func (r *RuleAPIConfig) Check() configerr.ConfigError {
 		return cfgErr
 	}
 
+	for _, h := range r.HeaderSet {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, h := range r.HeaderAdd {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, h := range r.HeaderDel {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, q := range r.QuerySet {
+		err := q.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, q := range r.QueryAdd {
+		err := q.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, q := range r.QueryDel {
+		err := q.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
 	return nil
 }

+ 4 - 4
src/config/rules/action/api/headerconfig.go

@@ -6,21 +6,21 @@ import (
 	"github.com/SongZihuan/huan-proxy/src/utils"
 )
 
-type HeaderConfig struct {
+type ReqHeaderConfig struct {
 	Header string `yaml:"header"`
 	Value  string `yaml:"value"`
 }
 
-func (h *HeaderConfig) SetDefault() {
+func (h *ReqHeaderConfig) SetDefault() {
 
 }
 
-func (h *HeaderConfig) Check() configerr.ConfigError {
+func (h *ReqHeaderConfig) Check() configerr.ConfigError {
 	if h.Header == "" {
 		return configerr.NewConfigError("header name is empty")
 	}
 
-	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer {
+	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer || h.Header == TransferEncoding {
 		return configerr.NewConfigError(fmt.Sprintf("header %s use by http system", h.Header))
 	}
 

+ 4 - 4
src/config/rules/action/api/headerdelconfig.go

@@ -6,20 +6,20 @@ import (
 	"github.com/SongZihuan/huan-proxy/src/utils"
 )
 
-type HeaderDelConfig struct {
+type ReqHeaderDelConfig struct {
 	Header string `yaml:"header"`
 }
 
-func (h *HeaderDelConfig) SetDefault() {
+func (h *ReqHeaderDelConfig) SetDefault() {
 
 }
 
-func (h *HeaderDelConfig) Check() configerr.ConfigError {
+func (h *ReqHeaderDelConfig) Check() configerr.ConfigError {
 	if h.Header == "" {
 		return configerr.NewConfigError("header name is empty")
 	}
 
-	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer {
+	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer || h.Header == TransferEncoding {
 		return configerr.NewConfigError(fmt.Sprintf("header %s use by http system", h.Header))
 	}
 

+ 3 - 3
src/config/rules/action/api/protectheader.go

@@ -2,14 +2,14 @@ package api
 
 const XHuanProxyHeaer = "X-Huan-Proxy"
 const ViaHeader = "Via"
+const TransferEncoding = "Transfer-Encoding"
 
-var WarningHeader = []string{
+var WarningReqHeader = []string{
 	"Host",
 	"Referer",
 	"User-Agent",
 	"Forwarded",
 	"Content-Length",
-	"Transfer-Encoding",
 	"Upgrade",
 	"Connection",
 	"X-Forwarded-For",
@@ -20,7 +20,7 @@ var WarningHeader = []string{
 }
 
 func isNotGoodHeader(header string) bool {
-	for _, h := range WarningHeader {
+	for _, h := range WarningReqHeader {
 		if h == header {
 			return true
 		}

+ 1 - 0
src/config/rules/action/respheader/README

@@ -0,0 +1 @@
+所有模式均有

+ 40 - 0
src/config/rules/action/respheader/headerconfig.go

@@ -0,0 +1,40 @@
+package respheader
+
+import (
+	"fmt"
+	"github.com/SongZihuan/huan-proxy/src/config/configerr"
+	"github.com/SongZihuan/huan-proxy/src/utils"
+)
+
+type RespHeaderConfig struct {
+	Header string `yaml:"header"`
+	Value  string `yaml:"value"`
+}
+
+func (h *RespHeaderConfig) SetDefault() {
+
+}
+
+func (h *RespHeaderConfig) Check() configerr.ConfigError {
+	if h.Header == "" {
+		return configerr.NewConfigError("header name is empty")
+	}
+
+	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer || h.Header == ContentLength || h.Header == TransferEncoding {
+		return configerr.NewConfigError(fmt.Sprintf("header %s use by http system", h.Header))
+	}
+
+	if !utils.IsValidHTTPHeaderKey(h.Header) {
+		return configerr.NewConfigError(fmt.Sprintf("header %s is not valid", h.Header))
+	}
+
+	if isNotGoodHeader(h.Header) {
+		_ = configerr.NewConfigWarning(fmt.Sprintf("header %s use by http system", h.Header))
+	}
+
+	if h.Value == "" {
+		_ = configerr.NewConfigWarning(fmt.Sprintf("the value of header %s is empty, but maybe it is not delete from requests", h.Header))
+	}
+
+	return nil
+}

+ 35 - 0
src/config/rules/action/respheader/headerdelconfig.go

@@ -0,0 +1,35 @@
+package respheader
+
+import (
+	"fmt"
+	"github.com/SongZihuan/huan-proxy/src/config/configerr"
+	"github.com/SongZihuan/huan-proxy/src/utils"
+)
+
+type RespHeaderDelConfig struct {
+	Header string `yaml:"header"`
+}
+
+func (h *RespHeaderDelConfig) SetDefault() {
+
+}
+
+func (h *RespHeaderDelConfig) Check() configerr.ConfigError {
+	if h.Header == "" {
+		return configerr.NewConfigError("header name is empty")
+	}
+
+	if h.Header == ViaHeader || h.Header == XHuanProxyHeaer || h.Header == ContentLength || h.Header == TransferEncoding {
+		return configerr.NewConfigError(fmt.Sprintf("header %s use by http system", h.Header))
+	}
+
+	if !utils.IsValidHTTPHeaderKey(h.Header) {
+		return configerr.NewConfigError(fmt.Sprintf("header %s is not valid", h.Header))
+	}
+
+	if isNotGoodHeader(h.Header) {
+		_ = configerr.NewConfigWarning(fmt.Sprintf("header %s use by http system", h.Header))
+	}
+
+	return nil
+}

+ 25 - 0
src/config/rules/action/respheader/protectheader.go

@@ -0,0 +1,25 @@
+package respheader
+
+const XHuanProxyHeaer = "X-Huan-Proxy"
+const ViaHeader = "Via"
+const ContentLength = "Content-Length"
+const TransferEncoding = "Transfer-Encoding"
+
+var WarningRespHeader = []string{
+	"Host",
+	"Referer",
+	"User-Agent",
+	"Upgrade",
+	"Connection",
+	"Cache-Control",
+}
+
+func isNotGoodHeader(header string) bool {
+	for _, h := range WarningRespHeader {
+		if h == header {
+			return true
+		}
+	}
+
+	return false
+}

+ 50 - 0
src/config/rules/action/respheader/respheaderconfig.go

@@ -0,0 +1,50 @@
+package respheader
+
+import (
+	"github.com/SongZihuan/huan-proxy/src/config/configerr"
+)
+
+type SetRespHeaderConfig struct {
+	HeaderSet []*RespHeaderConfig    `yaml:"headerret"`
+	HeaderAdd []*RespHeaderConfig    `yaml:"headeradd"`
+	HeaderDel []*RespHeaderDelConfig `yaml:"headerdel"`
+}
+
+func (s *SetRespHeaderConfig) SetDefault() {
+	for _, h := range s.HeaderSet {
+		h.SetDefault()
+	}
+
+	for _, h := range s.HeaderAdd {
+		h.SetDefault()
+	}
+
+	for _, h := range s.HeaderDel {
+		h.SetDefault()
+	}
+}
+
+func (s *SetRespHeaderConfig) Check() configerr.ConfigError {
+	for _, h := range s.HeaderSet {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, h := range s.HeaderAdd {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	for _, h := range s.HeaderDel {
+		err := h.Check()
+		if err != nil && err.IsError() {
+			return err
+		}
+	}
+
+	return nil
+}

+ 6 - 4
src/config/rules/ruleconfig.go

@@ -7,6 +7,7 @@ import (
 	"github.com/SongZihuan/huan-proxy/src/config/rules/action/file"
 	"github.com/SongZihuan/huan-proxy/src/config/rules/action/redirect"
 	"github.com/SongZihuan/huan-proxy/src/config/rules/action/remotetrust"
+	"github.com/SongZihuan/huan-proxy/src/config/rules/action/respheader"
 	"github.com/SongZihuan/huan-proxy/src/config/rules/match"
 )
 
@@ -23,10 +24,11 @@ type RuleConfig struct {
 	match.MatchConfig             `yaml:",inline"`
 	remotetrust.RemoteTrustConfig `yaml:",inline"`
 
-	File     file.RuleFileConfig         `yaml:"file"`
-	Dir      dir.RuleDirConfig           `yaml:"dir"`
-	Api      api.RuleAPIConfig           `yaml:"api"`
-	Redirect redirect.RuleRedirectConfig `yaml:"redirect"`
+	File       file.RuleFileConfig            `yaml:"file"`
+	Dir        dir.RuleDirConfig              `yaml:"dir"`
+	Api        api.RuleAPIConfig              `yaml:"api"`
+	Redirect   redirect.RuleRedirectConfig    `yaml:"redirect"`
+	RespHeader respheader.SetRespHeaderConfig `yaml:"respHeader"`
 }
 
 func (p *RuleConfig) SetDefault() {

+ 9 - 9
src/config/rulescompile/actioncompile/apicompile/api.go

@@ -17,9 +17,9 @@ type RuleAPICompileConfig struct {
 	AddPath   string
 	SubPath   string
 	Rewrite   *rewritecompile.RewriteCompileConfig
-	HeaderSet []*HeaderCompileConfig
-	HeaderAdd []*HeaderCompileConfig
-	HeaderDel []*HeaderDelCompileConfig
+	HeaderSet []*ReqHeaderCompileConfig
+	HeaderAdd []*ReqHeaderCompileConfig
+	HeaderDel []*ReqHeaderDelCompileConfig
 	QuerySet  []*QueryCompileConfig
 	QueryAdd  []*QueryCompileConfig
 	QueryDel  []*QueryDelCompileConfig
@@ -39,27 +39,27 @@ func NewRuleAPICompileConfig(r *api.RuleAPIConfig) (*RuleAPICompileConfig, error
 
 	server := httputil.NewSingleHostReverseProxy(targetURL)
 
-	HeaderSet := make([]*HeaderCompileConfig, 0, len(r.HeaderSet))
+	HeaderSet := make([]*ReqHeaderCompileConfig, 0, len(r.HeaderSet))
 	for _, v := range r.HeaderSet {
-		h, err := NewHeaderCompileConfig(v)
+		h, err := NewReqHeaderCompileConfig(v)
 		if err != nil {
 			return nil, err
 		}
 		HeaderSet = append(HeaderSet, h)
 	}
 
-	HeaderAdd := make([]*HeaderCompileConfig, 0, len(r.HeaderAdd))
+	HeaderAdd := make([]*ReqHeaderCompileConfig, 0, len(r.HeaderAdd))
 	for _, v := range r.HeaderAdd {
-		h, err := NewHeaderCompileConfig(v)
+		h, err := NewReqHeaderCompileConfig(v)
 		if err != nil {
 			return nil, err
 		}
 		HeaderAdd = append(HeaderAdd, h)
 	}
 
-	HeaderDel := make([]*HeaderDelCompileConfig, 0, len(r.HeaderDel))
+	HeaderDel := make([]*ReqHeaderDelCompileConfig, 0, len(r.HeaderDel))
 	for _, v := range r.HeaderDel {
-		h, err := NewHeaderDelCompileConfig(v)
+		h, err := NewReqHeaderDelCompileConfig(v)
 		if err != nil {
 			return nil, err
 		}

+ 3 - 3
src/config/rulescompile/actioncompile/apicompile/headerconfig.go

@@ -2,13 +2,13 @@ package apicompile
 
 import "github.com/SongZihuan/huan-proxy/src/config/rules/action/api"
 
-type HeaderCompileConfig struct {
+type ReqHeaderCompileConfig struct {
 	Header string `yaml:"header"`
 	Value  string `yaml:"value"`
 }
 
-func NewHeaderCompileConfig(h *api.HeaderConfig) (*HeaderCompileConfig, error) {
-	return &HeaderCompileConfig{
+func NewReqHeaderCompileConfig(h *api.ReqHeaderConfig) (*ReqHeaderCompileConfig, error) {
+	return &ReqHeaderCompileConfig{
 		Header: h.Header,
 		Value:  h.Value,
 	}, nil

+ 3 - 3
src/config/rulescompile/actioncompile/apicompile/headerdelconfig.go

@@ -2,12 +2,12 @@ package apicompile
 
 import "github.com/SongZihuan/huan-proxy/src/config/rules/action/api"
 
-type HeaderDelCompileConfig struct {
+type ReqHeaderDelCompileConfig struct {
 	Header string `yaml:"header"`
 }
 
-func NewHeaderDelCompileConfig(h *api.HeaderDelConfig) (*HeaderDelCompileConfig, error) {
-	return &HeaderDelCompileConfig{
+func NewReqHeaderDelCompileConfig(h *api.ReqHeaderDelConfig) (*ReqHeaderDelCompileConfig, error) {
+	return &ReqHeaderDelCompileConfig{
 		Header: h.Header,
 	}, nil
 }

+ 17 - 0
src/config/rulescompile/actioncompile/respheadercompile/headerconfig.go

@@ -0,0 +1,17 @@
+package respheadercompile
+
+import (
+	"github.com/SongZihuan/huan-proxy/src/config/rules/action/respheader"
+)
+
+type RespHeaderCompileConfig struct {
+	Header string `yaml:"header"`
+	Value  string `yaml:"value"`
+}
+
+func NewRespHeaderCompileConfig(h *respheader.RespHeaderConfig) (*RespHeaderCompileConfig, error) {
+	return &RespHeaderCompileConfig{
+		Header: h.Header,
+		Value:  h.Value,
+	}, nil
+}

+ 15 - 0
src/config/rulescompile/actioncompile/respheadercompile/headerdelconfig.go

@@ -0,0 +1,15 @@
+package respheadercompile
+
+import (
+	"github.com/SongZihuan/huan-proxy/src/config/rules/action/respheader"
+)
+
+type RespHeaderDelCompileConfig struct {
+	Header string `yaml:"header"`
+}
+
+func NewRespHeaderDelCompileConfig(h *respheader.RespHeaderDelConfig) (*RespHeaderDelCompileConfig, error) {
+	return &RespHeaderDelCompileConfig{
+		Header: h.Header,
+	}, nil
+}

+ 46 - 0
src/config/rulescompile/actioncompile/respheadercompile/respheaderconfig.go

@@ -0,0 +1,46 @@
+package respheadercompile
+
+import (
+	"github.com/SongZihuan/huan-proxy/src/config/rules/action/respheader"
+)
+
+type SetRespHeaderCompileConfig struct {
+	HeaderSet []*RespHeaderCompileConfig    `yaml:"headerret"`
+	HeaderAdd []*RespHeaderCompileConfig    `yaml:"headeradd"`
+	HeaderDel []*RespHeaderDelCompileConfig `yaml:"headerdel"`
+}
+
+func NewSetRespHeaderCompileConfig(r *respheader.SetRespHeaderConfig) (*SetRespHeaderCompileConfig, error) {
+	HeaderSet := make([]*RespHeaderCompileConfig, 0, len(r.HeaderSet))
+	for _, v := range r.HeaderSet {
+		h, err := NewRespHeaderCompileConfig(v)
+		if err != nil {
+			return nil, err
+		}
+		HeaderSet = append(HeaderSet, h)
+	}
+
+	HeaderAdd := make([]*RespHeaderCompileConfig, 0, len(r.HeaderAdd))
+	for _, v := range r.HeaderAdd {
+		h, err := NewRespHeaderCompileConfig(v)
+		if err != nil {
+			return nil, err
+		}
+		HeaderAdd = append(HeaderAdd, h)
+	}
+
+	HeaderDel := make([]*RespHeaderDelCompileConfig, 0, len(r.HeaderDel))
+	for _, v := range r.HeaderDel {
+		h, err := NewRespHeaderDelCompileConfig(v)
+		if err != nil {
+			return nil, err
+		}
+		HeaderDel = append(HeaderDel, h)
+	}
+
+	return &SetRespHeaderCompileConfig{
+		HeaderSet: HeaderSet,
+		HeaderAdd: HeaderAdd,
+		HeaderDel: HeaderDel,
+	}, nil
+}

+ 12 - 0
src/config/rulescompile/ruleconfig.go

@@ -8,6 +8,7 @@ import (
 	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/filecompile"
 	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/redirectcompile"
 	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/remotetrustcompile"
+	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/respheadercompile"
 	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/matchcompile"
 )
 
@@ -42,6 +43,8 @@ type RuleCompileConfig struct {
 	Dir      *dircompile.RuleDirCompileConfig
 	Api      *apicompile.RuleAPICompileConfig
 	Redirect *redirectcompile.RuleRedirectCompileConfig
+
+	RespHeader *respheadercompile.SetRespHeaderCompileConfig
 }
 
 func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
@@ -60,6 +63,11 @@ func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
 		return nil, err
 	}
 
+	respHeader, err := respheadercompile.NewSetRespHeaderCompileConfig(&r.RespHeader)
+	if err != nil {
+		return nil, err
+	}
+
 	if typeID == ProxyTypeFile {
 		file, err := filecompile.NewRuleFileCompileConfig(&r.File)
 		if err != nil {
@@ -71,6 +79,7 @@ func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
 			MatchCompileConfig:       match,
 			RemoteTrustCompileConfig: remoteTrusts,
 			File:                     file,
+			RespHeader:               respHeader,
 		}, nil
 	} else if typeID == ProxyTypeDir {
 		dir, err := dircompile.NewRuleDirCompileConfig(&r.Dir)
@@ -83,6 +92,7 @@ func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
 			MatchCompileConfig:       match,
 			RemoteTrustCompileConfig: remoteTrusts,
 			Dir:                      dir,
+			RespHeader:               respHeader,
 		}, nil
 	} else if typeID == ProxyTypeAPI {
 		api, err := apicompile.NewRuleAPICompileConfig(&r.Api)
@@ -95,6 +105,7 @@ func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
 			MatchCompileConfig:       match,
 			RemoteTrustCompileConfig: remoteTrusts,
 			Api:                      api,
+			RespHeader:               respHeader,
 		}, nil
 	} else if typeID == ProxyTypeRedirect {
 		redirect, err := redirectcompile.NewRuleAPICompileConfig(&r.Redirect)
@@ -107,6 +118,7 @@ func NewRuleCompileConfig(r *rules.RuleConfig) (*RuleCompileConfig, error) {
 			MatchCompileConfig:       match,
 			RemoteTrustCompileConfig: remoteTrusts,
 			Redirect:                 redirect,
+			RespHeader:               respHeader,
 		}, nil
 	} else {
 		return nil, fmt.Errorf("error rule type")

+ 3 - 0
src/server/context/context.go

@@ -3,6 +3,7 @@ package context
 import (
 	"fmt"
 	"github.com/SongZihuan/huan-proxy/src/config/rulescompile"
+	"github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/respheadercompile"
 	"github.com/SongZihuan/huan-proxy/src/server/request/proxyrequest"
 	"github.com/SongZihuan/huan-proxy/src/server/request/readonlyrequest"
 	"github.com/SongZihuan/huan-proxy/src/server/responsewriter"
@@ -17,6 +18,7 @@ type Context struct {
 	Request      *readonlyrequest.ReadOnlyRequest
 	ProxyRequest *proxyrequest.ProxyRequest
 	Rule         *rulescompile.RuleCompileConfig
+	RespHeader   *respheadercompile.SetRespHeaderCompileConfig
 }
 
 func NewContext(rule *rulescompile.RuleCompileConfig, w http.ResponseWriter, r *http.Request) *Context {
@@ -32,6 +34,7 @@ func NewContext(rule *rulescompile.RuleCompileConfig, w http.ResponseWriter, r *
 		Request:      readonlyrequest.NewReadOnlyRequest(r),
 		ProxyRequest: proxyRequest,
 		Rule:         rule,
+		RespHeader:   rule.RespHeader,
 	}
 }
 

+ 2 - 0
src/server/core/normalserver.go → src/server/core/coreserver.go

@@ -40,6 +40,8 @@ func (c *CoreServer) CoreServeHTTP(writer http.ResponseWriter, r *http.Request)
 				continue RuleCycle
 			}
 
+			c.WriteRespHeader(ctx)
+
 			ctx.MustWriteToResponse()
 			return
 

+ 19 - 0
src/server/core/writerespheader.go

@@ -0,0 +1,19 @@
+package core
+
+import "github.com/SongZihuan/huan-proxy/src/server/context"
+
+func (c *CoreServer) WriteRespHeader(ctx *context.Context) {
+	writerHeader := ctx.Writer.Header()
+
+	for _, h := range ctx.Rule.RespHeader.HeaderSet {
+		writerHeader.Set(h.Header, h.Value)
+	}
+
+	for _, h := range ctx.Rule.RespHeader.HeaderAdd {
+		writerHeader.Add(h.Header, h.Value)
+	}
+
+	for _, h := range ctx.Rule.RespHeader.HeaderDel {
+		writerHeader.Del(h.Header)
+	}
+}