From 58bce36fb3af12257387a3d3d44abffa350e7cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Wed, 16 Sep 2020 20:29:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E7=AC=A6=E7=BC=96?= =?UTF-8?q?=E7=A0=81/HTTP=20Header=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 4 +- go.sum | 2 + internal/apis/api_node.go | 2 + internal/db/models/http_header_dao.go | 69 ++++- internal/db/models/http_header_policy_dao.go | 265 ++++++++++++++++++ .../db/models/http_header_policy_dao_test.go | 5 + .../db/models/http_header_policy_model.go | 36 +++ .../db/models/http_header_policy_model_ext.go | 1 + internal/db/models/http_web_dao.go | 72 ++++- internal/db/models/http_web_model.go | 62 ++-- internal/db/models/origin_server_dao.go | 84 +++--- internal/db/models/origin_server_model.go | 100 +++---- internal/db/models/server_dao.go | 12 + internal/rpc/services/service_base.go | 4 + internal/rpc/services/service_http_header.go | 61 ++++ .../services/service_http_header_policy.go | 122 ++++++++ internal/rpc/services/service_http_web.go | 51 ++++ internal/rpc/services/service_server.go | 22 +- 18 files changed, 857 insertions(+), 117 deletions(-) create mode 100644 internal/db/models/http_header_policy_dao.go create mode 100644 internal/db/models/http_header_policy_dao_test.go create mode 100644 internal/db/models/http_header_policy_model.go create mode 100644 internal/db/models/http_header_policy_model_ext.go create mode 100644 internal/rpc/services/service_base.go create mode 100644 internal/rpc/services/service_http_header.go create mode 100644 internal/rpc/services/service_http_header_policy.go diff --git a/go.mod b/go.mod index b87b01c3..9dccbcfa 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,9 @@ require ( github.com/go-sql-driver/mysql v1.5.0 github.com/go-yaml/yaml v2.1.0+incompatible github.com/golang/protobuf v1.4.2 - github.com/iwind/TeaGo v0.0.0-20200910072805-729cffe36729 + github.com/iwind/TeaGo v0.0.0-20200916035436-dbdbf25f8524 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect github.com/pkg/sftp v1.12.0 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a google.golang.org/grpc v1.32.0 diff --git a/go.sum b/go.sum index 7ec9b64b..45ce1c12 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/iwind/TeaGo v0.0.0-20200910072805-729cffe36729 h1:/v0WhSFVeNay/dA5zU9iCBXlgVDfxnztuanlauXE0gM= github.com/iwind/TeaGo v0.0.0-20200910072805-729cffe36729/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= +github.com/iwind/TeaGo v0.0.0-20200916035436-dbdbf25f8524 h1:WnARCxusBjX5vJ8E71AjhuxSeAMGfEiYvi42XVK/Yf8= +github.com/iwind/TeaGo v0.0.0-20200916035436-dbdbf25f8524/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= diff --git a/internal/apis/api_node.go b/internal/apis/api_node.go index e63abaf5..99a2ca2d 100644 --- a/internal/apis/api_node.go +++ b/internal/apis/api_node.go @@ -62,6 +62,8 @@ func (this *APINode) listenRPC() error { pb.RegisterHTTPWebServiceServer(rpcServer, &services.HTTPWebService{}) pb.RegisterReverseProxyServiceServer(rpcServer, &services.ReverseProxyService{}) pb.RegisterHTTPGzipServiceServer(rpcServer, &services.HTTPGzipService{}) + pb.RegisterHTTPHeaderPolicyServiceServer(rpcServer, &services.HTTPHeaderPolicyService{}) + pb.RegisterHTTPHeaderServiceServer(rpcServer, &services.HTTPHeaderService{}) err = rpcServer.Serve(listener) if err != nil { return errors.New("[API]start rpc failed: " + err.Error()) diff --git a/internal/db/models/http_header_dao.go b/internal/db/models/http_header_dao.go index 6c0036a7..fca24023 100644 --- a/internal/db/models/http_header_dao.go +++ b/internal/db/models/http_header_dao.go @@ -1,9 +1,13 @@ package models import ( + "encoding/json" + "errors" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" _ "github.com/go-sql-driver/mysql" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/dbs" + "github.com/iwind/TeaGo/types" ) const ( @@ -27,7 +31,7 @@ func NewHTTPHeaderDAO() *HTTPHeaderDAO { var SharedHTTPHeaderDAO = NewHTTPHeaderDAO() // 启用条目 -func (this *HTTPHeaderDAO) EnableHTTPHeader(id uint32) error { +func (this *HTTPHeaderDAO) EnableHTTPHeader(id int64) error { _, err := this.Query(). Pk(id). Set("state", HTTPHeaderStateEnabled). @@ -45,7 +49,7 @@ func (this *HTTPHeaderDAO) DisableHTTPHeader(id uint32) error { } // 查找启用中的条目 -func (this *HTTPHeaderDAO) FindEnabledHTTPHeader(id uint32) (*HTTPHeader, error) { +func (this *HTTPHeaderDAO) FindEnabledHTTPHeader(id int64) (*HTTPHeader, error) { result, err := this.Query(). Pk(id). Attr("state", HTTPHeaderStateEnabled). @@ -57,9 +61,68 @@ func (this *HTTPHeaderDAO) FindEnabledHTTPHeader(id uint32) (*HTTPHeader, error) } // 根据主键查找名称 -func (this *HTTPHeaderDAO) FindHTTPHeaderName(id uint32) (string, error) { +func (this *HTTPHeaderDAO) FindHTTPHeaderName(id int64) (string, error) { return this.Query(). Pk(id). Result("name"). FindStringCol("") } + +// 创建Header +func (this *HTTPHeaderDAO) CreateHeader(name string, value string) (int64, error) { + op := NewHTTPHeaderOperator() + op.State = HTTPHeaderStateEnabled + op.IsOn = true + op.Name = name + op.Value = value + _, err := this.Save(op) + if err != nil { + return 0, err + } + return types.Int64(op.Id), nil +} + +// 修改Header +func (this *HTTPHeaderDAO) UpdateHeader(headerId int64, name string, value string) error { + if headerId <= 0 { + return errors.New("invalid headerId") + } + + op := NewHTTPHeaderOperator() + op.Id = headerId + op.Name = name + op.Value = value + _, err := this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 组合Header配置 +func (this *HTTPHeaderDAO) ComposeHeaderConfig(headerId int64) (*shared.HTTPHeaderConfig, error) { + header, err := this.FindEnabledHTTPHeader(headerId) + if err != nil { + return nil, err + } + if header == nil { + return nil, nil + } + + config := &shared.HTTPHeaderConfig{} + config.Id = int64(header.Id) + config.IsOn = header.IsOn == 1 + config.Name = header.Name + config.Value = header.Value + + if len(header.Status) > 0 { + status := &shared.HTTPStatusConfig{} + err = json.Unmarshal([]byte(header.Status), status) + if err != nil { + return nil, err + } + config.Status = status + } + + return config, nil +} diff --git a/internal/db/models/http_header_policy_dao.go b/internal/db/models/http_header_policy_dao.go new file mode 100644 index 00000000..96feb92c --- /dev/null +++ b/internal/db/models/http_header_policy_dao.go @@ -0,0 +1,265 @@ +package models + +import ( + "encoding/json" + "errors" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" + "github.com/iwind/TeaGo/types" +) + +const ( + HTTPHeaderPolicyStateEnabled = 1 // 已启用 + HTTPHeaderPolicyStateDisabled = 0 // 已禁用 +) + +type HTTPHeaderPolicyDAO dbs.DAO + +func NewHTTPHeaderPolicyDAO() *HTTPHeaderPolicyDAO { + return dbs.NewDAO(&HTTPHeaderPolicyDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeHTTPHeaderPolicies", + Model: new(HTTPHeaderPolicy), + PkName: "id", + }, + }).(*HTTPHeaderPolicyDAO) +} + +var SharedHTTPHeaderPolicyDAO = NewHTTPHeaderPolicyDAO() + +// 启用条目 +func (this *HTTPHeaderPolicyDAO) EnableHTTPHeaderPolicy(id int64) error { + _, err := this.Query(). + Pk(id). + Set("state", HTTPHeaderPolicyStateEnabled). + Update() + return err +} + +// 禁用条目 +func (this *HTTPHeaderPolicyDAO) DisableHTTPHeaderPolicy(id int64) error { + _, err := this.Query(). + Pk(id). + Set("state", HTTPHeaderPolicyStateDisabled). + Update() + return err +} + +// 查找启用中的条目 +func (this *HTTPHeaderPolicyDAO) FindEnabledHTTPHeaderPolicy(id int64) (*HTTPHeaderPolicy, error) { + result, err := this.Query(). + Pk(id). + Attr("state", HTTPHeaderPolicyStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*HTTPHeaderPolicy), err +} + +// 创建策略 +func (this *HTTPHeaderPolicyDAO) CreateHeaderPolicy() (int64, error) { + op := NewHTTPHeaderPolicyOperator() + op.IsOn = true + op.State = HTTPHeaderPolicyStateEnabled + _, err := this.Save(op) + if err != nil { + return 0, err + } + return types.Int64(op.Id), nil +} + +// 修改AddHeaders +func (this *HTTPHeaderPolicyDAO) UpdateAddingHeaders(policyId int64, headersJSON []byte) error { + if policyId <= 0 { + return errors.New("invalid policyId") + } + + op := NewHTTPHeaderPolicyOperator() + op.Id = policyId + op.AddHeaders = headersJSON + _, err := this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 修改SetHeaders +func (this *HTTPHeaderPolicyDAO) UpdateSettingHeaders(policyId int64, headersJSON []byte) error { + if policyId <= 0 { + return errors.New("invalid policyId") + } + + op := NewHTTPHeaderPolicyOperator() + op.Id = policyId + op.SetHeaders = headersJSON + _, err := this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 修改ReplaceHeaders +func (this *HTTPHeaderPolicyDAO) UpdateReplacingHeaders(policyId int64, headersJSON []byte) error { + if policyId <= 0 { + return errors.New("invalid policyId") + } + + op := NewHTTPHeaderPolicyOperator() + op.Id = policyId + op.ReplaceHeaders = headersJSON + _, err := this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 修改AddTrailers +func (this *HTTPHeaderPolicyDAO) UpdateAddingTrailers(policyId int64, headersJSON []byte) error { + if policyId <= 0 { + return errors.New("invalid policyId") + } + + op := NewHTTPHeaderPolicyOperator() + op.Id = policyId + op.AddTrailers = headersJSON + _, err := this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 修改DeleteHeaders +func (this *HTTPHeaderPolicyDAO) UpdateDeletingHeaders(policyId int64, headerNames []string) error { + if policyId <= 0 { + return errors.New("invalid policyId") + } + + namesJSON, err := json.Marshal(headerNames) + if err != nil { + return err + } + + op := NewHTTPHeaderPolicyOperator() + op.Id = policyId + op.DeleteHeaders = string(namesJSON) + _, err = this.Save(op) + + // TODO 更新相关配置 + + return err +} + +// 组合配置 +func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(headerPolicyId int64) (*shared.HTTPHeaderPolicy, error) { + policy, err := this.FindEnabledHTTPHeaderPolicy(headerPolicyId) + if err != nil { + return nil, err + } + if policy == nil { + return nil, nil + } + + config := &shared.HTTPHeaderPolicy{} + config.Id = int64(policy.Id) + config.IsOn = policy.IsOn == 1 + + // AddHeaders + if len(policy.AddHeaders) > 0 { + headers := []*shared.HTTPHeaderConfig{} + err = json.Unmarshal([]byte(policy.AddHeaders), &headers) + if err != nil { + return nil, err + } + if len(headers) > 0 { + for k, header := range headers { + headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(header.Id) + if err != nil { + return nil, err + } + headers[k] = headerConfig + } + + config.AddHeaders = headers + } + } + + // AddTrailers + if len(policy.AddTrailers) > 0 { + headers := []*shared.HTTPHeaderConfig{} + err = json.Unmarshal([]byte(policy.AddTrailers), &headers) + if err != nil { + return nil, err + } + if len(headers) > 0 { + for k, header := range headers { + headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(header.Id) + if err != nil { + return nil, err + } + headers[k] = headerConfig + } + config.AddTrailers = headers + } + } + + // SetHeaders + if len(policy.SetHeaders) > 0 { + headers := []*shared.HTTPHeaderConfig{} + err = json.Unmarshal([]byte(policy.SetHeaders), &headers) + if err != nil { + return nil, err + } + if len(headers) > 0 { + for k, header := range headers { + headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(header.Id) + if err != nil { + return nil, err + } + headers[k] = headerConfig + } + config.SetHeaders = headers + } + } + + // ReplaceHeaders + if len(policy.ReplaceHeaders) > 0 { + headers := []*shared.HTTPHeaderConfig{} + err = json.Unmarshal([]byte(policy.ReplaceHeaders), &headers) + if err != nil { + return nil, err + } + if len(headers) > 0 { + for k, header := range headers { + headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(header.Id) + if err != nil { + return nil, err + } + headers[k] = headerConfig + } + config.ReplaceHeaders = headers + } + } + + // Delete Headers + if len(policy.DeleteHeaders) > 0 { + headers := []string{} + err = json.Unmarshal([]byte(policy.DeleteHeaders), &headers) + if err != nil { + return nil, err + } + config.DeletedHeaders = headers + } + + // Expires + // TODO + + return config, nil +} diff --git a/internal/db/models/http_header_policy_dao_test.go b/internal/db/models/http_header_policy_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/http_header_policy_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/http_header_policy_model.go b/internal/db/models/http_header_policy_model.go new file mode 100644 index 00000000..9f44e2bb --- /dev/null +++ b/internal/db/models/http_header_policy_model.go @@ -0,0 +1,36 @@ +package models + +// +type HTTPHeaderPolicy struct { + Id uint32 `field:"id"` // ID + IsOn uint8 `field:"isOn"` // 是否启用 + State uint8 `field:"state"` // 状态 + AdminId uint32 `field:"adminId"` // 管理员ID + UserId uint32 `field:"userId"` // 用户ID + CreatedAt uint32 `field:"createdAt"` // 创建时间 + AddHeaders string `field:"addHeaders"` // 添加的Header + AddTrailers string `field:"addTrailers"` // 添加的Trailers + SetHeaders string `field:"setHeaders"` // 设置Header + ReplaceHeaders string `field:"replaceHeaders"` // 替换Header内容 + Expires string `field:"expires"` // Expires单独设置 + DeleteHeaders string `field:"deleteHeaders"` // 删除的Headers +} + +type HTTPHeaderPolicyOperator struct { + Id interface{} // ID + IsOn interface{} // 是否启用 + State interface{} // 状态 + AdminId interface{} // 管理员ID + UserId interface{} // 用户ID + CreatedAt interface{} // 创建时间 + AddHeaders interface{} // 添加的Header + AddTrailers interface{} // 添加的Trailers + SetHeaders interface{} // 设置Header + ReplaceHeaders interface{} // 替换Header内容 + Expires interface{} // Expires单独设置 + DeleteHeaders interface{} // 删除的Headers +} + +func NewHTTPHeaderPolicyOperator() *HTTPHeaderPolicyOperator { + return &HTTPHeaderPolicyOperator{} +} diff --git a/internal/db/models/http_header_policy_model_ext.go b/internal/db/models/http_header_policy_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/http_header_policy_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/http_web_dao.go b/internal/db/models/http_web_dao.go index ca035c66..8d5055f4 100644 --- a/internal/db/models/http_web_dao.go +++ b/internal/db/models/http_web_dao.go @@ -82,7 +82,29 @@ func (this *HTTPWebDAO) ComposeWebConfig(webId int64) (*serverconfigs.HTTPWebCon config.Gzip = gzipConfig } - // TODO charset + // charset + config.Charset = web.Charset + + // headers + if web.RequestHeaderPolicyId > 0 { + headerPolicy, err := SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(int64(web.RequestHeaderPolicyId)) + if err != nil { + return nil, err + } + if headerPolicy != nil { + config.RequestHeaders = headerPolicy + } + } + + if web.ResponseHeaderPolicyId > 0 { + headerPolicy, err := SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(int64(web.ResponseHeaderPolicyId)) + if err != nil { + return nil, err + } + if headerPolicy != nil { + config.ResponseHeaders = headerPolicy + } + } // TODO 更多配置 @@ -133,6 +155,54 @@ func (this *HTTPWebDAO) UpdateWebGzip(webId int64, gzipId int64) error { return this.NotifyUpdating(webId) } +// 修改字符编码 +func (this *HTTPWebDAO) UpdateWebCharset(webId int64, charset string) error { + if webId <= 0 { + return errors.New("invalid webId") + } + op := NewHTTPWebOperator() + op.Id = webId + op.Charset = charset + _, err := this.Save(op) + if err != nil { + return err + } + + return this.NotifyUpdating(webId) +} + +// 更改请求Header策略 +func (this *HTTPWebDAO) UpdateHTTPWebRequestHeaderPolicy(webId int64, headerPolicyId int64) error { + if webId <= 0 { + return errors.New("invalid webId") + } + op := NewHTTPWebOperator() + op.Id = webId + op.RequestHeaderPolicyId = headerPolicyId + _, err := this.Save(op) + if err != nil { + return err + } + + return this.NotifyUpdating(webId) +} + +// 更改响应Header策略 +func (this *HTTPWebDAO) UpdateHTTPWebResponseHeaderPolicy(webId int64, headerPolicyId int64) error { + if webId <= 0 { + return errors.New("invalid webId") + } + op := NewHTTPWebOperator() + op.Id = webId + op.ResponseHeaderPolicyId = headerPolicyId + _, err := this.Save(op) + if err != nil { + return err + } + + return this.NotifyUpdating(webId) +} + // 通知更新 func (this *HTTPWebDAO) NotifyUpdating(webId int64) error { err := SharedServerDAO.UpdateServerIsUpdatingWithWebId(webId) diff --git a/internal/db/models/http_web_model.go b/internal/db/models/http_web_model.go index 4d6d10a6..f225bf51 100644 --- a/internal/db/models/http_web_model.go +++ b/internal/db/models/http_web_model.go @@ -1,28 +1,52 @@ package models -// +// HTTP Web type HTTPWeb struct { - Id uint32 `field:"id"` // ID - IsOn uint8 `field:"isOn"` // 是否启用 - TemplateId uint32 `field:"templateId"` // 模版ID - AdminId uint32 `field:"adminId"` // 管理员ID - UserId uint32 `field:"userId"` // 用户ID - State uint8 `field:"state"` // 状态 - CreatedAt uint32 `field:"createdAt"` // 创建时间 - Root string `field:"root"` // 资源根目录 - GzipId uint32 `field:"gzipId"` // Gzip配置 + Id uint32 `field:"id"` // ID + IsOn uint8 `field:"isOn"` // 是否启用 + TemplateId uint32 `field:"templateId"` // 模版ID + AdminId uint32 `field:"adminId"` // 管理员ID + UserId uint32 `field:"userId"` // 用户ID + State uint8 `field:"state"` // 状态 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + Root string `field:"root"` // 资源根目录 + GzipId uint32 `field:"gzipId"` // Gzip配置 + Charset string `field:"charset"` // 字符集 + Shutdown string `field:"shutdown"` // 临时关闭页面配置 + Pages string `field:"pages"` // 特殊页面 + FirewallId uint32 `field:"firewallId"` // WAF ID + CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID + AccessLogPolicyId uint32 `field:"accessLogPolicyId"` // 访问日志策略ID + RedirectToHttps string `field:"redirectToHttps"` // 跳转到HTTPS设置 + Indexes string `field:"indexes"` // 首页文件列表 + MaxRequestBodySize string `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸 + StatPolicyId uint32 `field:"statPolicyId"` // 统计策略ID + RequestHeaderPolicyId uint32 `field:"requestHeaderPolicyId"` // Request Header策略ID + ResponseHeaderPolicyId uint32 `field:"responseHeaderPolicyId"` // Response Header策略 } type HTTPWebOperator struct { - Id interface{} // ID - IsOn interface{} // 是否启用 - TemplateId interface{} // 模版ID - AdminId interface{} // 管理员ID - UserId interface{} // 用户ID - State interface{} // 状态 - CreatedAt interface{} // 创建时间 - Root interface{} // 资源根目录 - GzipId interface{} // Gzip配置 + Id interface{} // ID + IsOn interface{} // 是否启用 + TemplateId interface{} // 模版ID + AdminId interface{} // 管理员ID + UserId interface{} // 用户ID + State interface{} // 状态 + CreatedAt interface{} // 创建时间 + Root interface{} // 资源根目录 + GzipId interface{} // Gzip配置 + Charset interface{} // 字符集 + Shutdown interface{} // 临时关闭页面配置 + Pages interface{} // 特殊页面 + FirewallId interface{} // WAF ID + CachePolicyId interface{} // 缓存策略ID + AccessLogPolicyId interface{} // 访问日志策略ID + RedirectToHttps interface{} // 跳转到HTTPS设置 + Indexes interface{} // 首页文件列表 + MaxRequestBodySize interface{} // 最大允许的请求内容尺寸 + StatPolicyId interface{} // 统计策略ID + RequestHeaderPolicyId interface{} // Request Header策略ID + ResponseHeaderPolicyId interface{} // Response Header策略 } func NewHTTPWebOperator() *HTTPWebOperator { diff --git a/internal/db/models/origin_server_dao.go b/internal/db/models/origin_server_dao.go index 31da36db..f5467ab6 100644 --- a/internal/db/models/origin_server_dao.go +++ b/internal/db/models/origin_server_dao.go @@ -110,99 +110,103 @@ func (this *OriginServerDAO) ComposeOriginConfig(originId int64) (*serverconfigs return nil, errors.New("not found") } - addr := &serverconfigs.NetworkAddressConfig{} + config := &serverconfigs.OriginServerConfig{ + Id: int64(origin.Id), + IsOn: origin.IsOn == 1, + Version: int(origin.Version), + Name: origin.Name, + Description: origin.Description, + Code: origin.Code, + Weight: uint(origin.Weight), + MaxFails: int(origin.MaxFails), + MaxConns: int(origin.MaxConns), + MaxIdleConns: int(origin.MaxIdleConns), + RequestURI: origin.HttpRequestURI, + Host: origin.Host, + } + if len(origin.Addr) > 0 && origin.Addr != "null" { + addr := &serverconfigs.NetworkAddressConfig{} err = json.Unmarshal([]byte(origin.Addr), addr) if err != nil { return nil, err } + config.Addr = addr } - connTimeout := &shared.TimeDuration{} if len(origin.ConnTimeout) > 0 && origin.ConnTimeout != "null" { + connTimeout := &shared.TimeDuration{} err = json.Unmarshal([]byte(origin.ConnTimeout), &connTimeout) if err != nil { return nil, err } + config.ConnTimeout = connTimeout } - readTimeout := &shared.TimeDuration{} if len(origin.ReadTimeout) > 0 && origin.ReadTimeout != "null" { + readTimeout := &shared.TimeDuration{} err = json.Unmarshal([]byte(origin.ReadTimeout), &readTimeout) if err != nil { return nil, err } + config.ReadTimeout = readTimeout } - idleTimeout := &shared.TimeDuration{} if len(origin.IdleTimeout) > 0 && origin.IdleTimeout != "null" { + idleTimeout := &shared.TimeDuration{} err = json.Unmarshal([]byte(origin.IdleTimeout), &idleTimeout) if err != nil { return nil, err } + config.IdleTimeout = idleTimeout } - requestHeaders := &shared.HTTPHeadersConfig{} - if len(origin.HttpRequestHeaders) > 0 && origin.HttpRequestHeaders != "null" { - err = json.Unmarshal([]byte(origin.HttpRequestHeaders), requestHeaders) + if origin.RequestHeaderPolicyId > 0 { + policyConfig, err := SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(int64(origin.RequestHeaderPolicyId)) if err != nil { return nil, err } - } - - responseHeaders := &shared.HTTPHeadersConfig{} - if len(origin.HttpResponseHeaders) > 0 && origin.HttpResponseHeaders != "null" { - err = json.Unmarshal([]byte(origin.HttpResponseHeaders), responseHeaders) - if err != nil { - return nil, err + if policyConfig != nil { + config.RequestHeaders = policyConfig + } + } + + if origin.ResponseHeaderPolicyId > 0 { + policyConfig, err := SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(int64(origin.ResponseHeaderPolicyId)) + if err != nil { + return nil, err + } + if policyConfig != nil { + config.ResponseHeaders = policyConfig } } - healthCheck := &serverconfigs.HealthCheckConfig{} if len(origin.HealthCheck) > 0 && origin.HealthCheck != "null" { + healthCheck := &serverconfigs.HealthCheckConfig{} err = json.Unmarshal([]byte(origin.HealthCheck), healthCheck) if err != nil { return nil, err } + config.HealthCheck = healthCheck } - cert := &sslconfigs.SSLCertConfig{} if len(origin.Cert) > 0 && origin.Cert != "null" { + cert := &sslconfigs.SSLCertConfig{} err = json.Unmarshal([]byte(origin.Cert), cert) if err != nil { return nil, err } + config.Cert = cert } - ftp := &serverconfigs.OriginServerFTPConfig{} if len(origin.Ftp) > 0 && origin.Ftp != "null" { + ftp := &serverconfigs.OriginServerFTPConfig{} err = json.Unmarshal([]byte(origin.Ftp), ftp) if err != nil { return nil, err } + config.FTP = ftp } - return &serverconfigs.OriginServerConfig{ - Id: int64(origin.Id), - IsOn: origin.IsOn == 1, - Version: int(origin.Version), - Name: origin.Name, - Addr: addr, - Description: origin.Description, - Code: origin.Code, - Weight: uint(origin.Weight), - ConnTimeout: connTimeout, - ReadTimeout: readTimeout, - IdleTimeout: idleTimeout, - MaxFails: int(origin.MaxFails), - MaxConns: int(origin.MaxConns), - MaxIdleConns: int(origin.MaxIdleConns), - RequestURI: origin.HttpRequestURI, - Host: origin.Host, - RequestHeaders: requestHeaders, - ResponseHeaders: responseHeaders, - HealthCheck: healthCheck, - Cert: cert, - FTP: ftp, - }, nil + return config, nil } diff --git a/internal/db/models/origin_server_model.go b/internal/db/models/origin_server_model.go index 3594beab..99ecf411 100644 --- a/internal/db/models/origin_server_model.go +++ b/internal/db/models/origin_server_model.go @@ -2,59 +2,59 @@ package models // 源站 type OriginServer struct { - Id uint32 `field:"id"` // ID - AdminId uint32 `field:"adminId"` // 管理员ID - UserId uint32 `field:"userId"` // 用户ID - IsOn uint8 `field:"isOn"` // 是否启用 - Name string `field:"name"` // 名称 - Version uint32 `field:"version"` // 版本 - Addr string `field:"addr"` // 地址 - Description string `field:"description"` // 描述 - Code string `field:"code"` // 代号 - Weight uint32 `field:"weight"` // 权重 - ConnTimeout string `field:"connTimeout"` // 连接超时 - ReadTimeout string `field:"readTimeout"` // 读超时 - IdleTimeout string `field:"idleTimeout"` // 空闲连接超时 - MaxFails uint32 `field:"maxFails"` // 最多失败次数 - MaxConns uint32 `field:"maxConns"` // 最大并发连接数 - MaxIdleConns uint32 `field:"maxIdleConns"` // 最多空闲连接数 - HttpRequestURI string `field:"httpRequestURI"` // 转发后的请求URI - HttpRequestHeaders string `field:"httpRequestHeaders"` // 请求Headers配置 - HttpResponseHeaders string `field:"httpResponseHeaders"` // 响应Headers配置 - Host string `field:"host"` // 自定义主机名 - HealthCheck string `field:"healthCheck"` // 健康检查设置 - Cert string `field:"cert"` // 证书设置 - Ftp string `field:"ftp"` // FTP相关设置 - CreatedAt uint32 `field:"createdAt"` // 创建时间 - State uint8 `field:"state"` // 状态 + Id uint32 `field:"id"` // ID + AdminId uint32 `field:"adminId"` // 管理员ID + UserId uint32 `field:"userId"` // 用户ID + IsOn uint8 `field:"isOn"` // 是否启用 + Name string `field:"name"` // 名称 + Version uint32 `field:"version"` // 版本 + Addr string `field:"addr"` // 地址 + Description string `field:"description"` // 描述 + Code string `field:"code"` // 代号 + Weight uint32 `field:"weight"` // 权重 + ConnTimeout string `field:"connTimeout"` // 连接超时 + ReadTimeout string `field:"readTimeout"` // 读超时 + IdleTimeout string `field:"idleTimeout"` // 空闲连接超时 + MaxFails uint32 `field:"maxFails"` // 最多失败次数 + MaxConns uint32 `field:"maxConns"` // 最大并发连接数 + MaxIdleConns uint32 `field:"maxIdleConns"` // 最多空闲连接数 + HttpRequestURI string `field:"httpRequestURI"` // 转发后的请求URI + RequestHeaderPolicyId uint32 `field:"requestHeaderPolicyId"` // 请求Header + ResponseHeaderPolicyId uint32 `field:"responseHeaderPolicyId"` // 响应Header + Host string `field:"host"` // 自定义主机名 + HealthCheck string `field:"healthCheck"` // 健康检查设置 + Cert string `field:"cert"` // 证书设置 + Ftp string `field:"ftp"` // FTP相关设置 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 } type OriginServerOperator struct { - Id interface{} // ID - AdminId interface{} // 管理员ID - UserId interface{} // 用户ID - IsOn interface{} // 是否启用 - Name interface{} // 名称 - Version interface{} // 版本 - Addr interface{} // 地址 - Description interface{} // 描述 - Code interface{} // 代号 - Weight interface{} // 权重 - ConnTimeout interface{} // 连接超时 - ReadTimeout interface{} // 读超时 - IdleTimeout interface{} // 空闲连接超时 - MaxFails interface{} // 最多失败次数 - MaxConns interface{} // 最大并发连接数 - MaxIdleConns interface{} // 最多空闲连接数 - HttpRequestURI interface{} // 转发后的请求URI - HttpRequestHeaders interface{} // 请求Headers配置 - HttpResponseHeaders interface{} // 响应Headers配置 - Host interface{} // 自定义主机名 - HealthCheck interface{} // 健康检查设置 - Cert interface{} // 证书设置 - Ftp interface{} // FTP相关设置 - CreatedAt interface{} // 创建时间 - State interface{} // 状态 + Id interface{} // ID + AdminId interface{} // 管理员ID + UserId interface{} // 用户ID + IsOn interface{} // 是否启用 + Name interface{} // 名称 + Version interface{} // 版本 + Addr interface{} // 地址 + Description interface{} // 描述 + Code interface{} // 代号 + Weight interface{} // 权重 + ConnTimeout interface{} // 连接超时 + ReadTimeout interface{} // 读超时 + IdleTimeout interface{} // 空闲连接超时 + MaxFails interface{} // 最多失败次数 + MaxConns interface{} // 最大并发连接数 + MaxIdleConns interface{} // 最多空闲连接数 + HttpRequestURI interface{} // 转发后的请求URI + RequestHeaderPolicyId interface{} // 请求Header + ResponseHeaderPolicyId interface{} // 响应Header + Host interface{} // 自定义主机名 + HealthCheck interface{} // 健康检查设置 + Cert interface{} // 证书设置 + Ftp interface{} // FTP相关设置 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 } func NewOriginServerOperator() *OriginServerOperator { diff --git a/internal/db/models/server_dao.go b/internal/db/models/server_dao.go index 1bb304b4..7bca8966 100644 --- a/internal/db/models/server_dao.go +++ b/internal/db/models/server_dao.go @@ -550,6 +550,18 @@ func (this *ServerDAO) UpdateServerIsUpdating(serverId int64, isUpdating bool) e return err } +// 查找WebId +func (this *ServerDAO) FindServerWebId(serverId int64) (int64, error) { + webId, err := this.Query(). + Pk(serverId). + Result("webId"). + FindIntCol(0) + if err != nil { + return 0, err + } + return int64(webId), nil +} + // 更新所有Web相关的处于更新状态 func (this *ServerDAO) UpdateServerIsUpdatingWithWebId(webId int64) error { _, err := this.Query(). diff --git a/internal/rpc/services/service_base.go b/internal/rpc/services/service_base.go new file mode 100644 index 00000000..10ff0b86 --- /dev/null +++ b/internal/rpc/services/service_base.go @@ -0,0 +1,4 @@ +package services + +type BaseService struct { +} diff --git a/internal/rpc/services/service_http_header.go b/internal/rpc/services/service_http_header.go new file mode 100644 index 00000000..87ff1b05 --- /dev/null +++ b/internal/rpc/services/service_http_header.go @@ -0,0 +1,61 @@ +package services + +import ( + "context" + "encoding/json" + "github.com/TeaOSLab/EdgeAPI/internal/db/models" + rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type HTTPHeaderService struct { +} + +// 创建Header +func (this *HTTPHeaderService) CreateHTTPHeader(ctx context.Context, req *pb.CreateHTTPHeaderRequest) (*pb.CreateHTTPHeaderResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + headerId, err := models.SharedHTTPHeaderDAO.CreateHeader(req.Name, req.Value) + if err != nil { + return nil, err + } + + return &pb.CreateHTTPHeaderResponse{HeaderId: headerId}, nil +} + +// 修改Header +func (this *HTTPHeaderService) UpdateHTTPHeader(ctx context.Context, req *pb.UpdateHTTPHeaderRequest) (*pb.UpdateHTTPHeaderResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderDAO.UpdateHeader(req.HeaderId, req.Name, req.Value) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderResponse{}, nil +} + +// 查找配置 +func (this *HTTPHeaderService) FindEnabledHTTPHeaderConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderConfigRequest) (*pb.FindEnabledHTTPHeaderConfigResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + config, err := models.SharedHTTPHeaderDAO.ComposeHeaderConfig(req.HeaderId) + if err != nil { + return nil, err + } + configData, err := json.Marshal(config) + if err != nil { + return nil, err + } + + return &pb.FindEnabledHTTPHeaderConfigResponse{Config: configData}, nil +} diff --git a/internal/rpc/services/service_http_header_policy.go b/internal/rpc/services/service_http_header_policy.go new file mode 100644 index 00000000..b18c6a17 --- /dev/null +++ b/internal/rpc/services/service_http_header_policy.go @@ -0,0 +1,122 @@ +package services + +import ( + "context" + "encoding/json" + "github.com/TeaOSLab/EdgeAPI/internal/db/models" + rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type HTTPHeaderPolicyService struct { +} + +// 查找策略配置 +func (this *HTTPHeaderPolicyService) FindEnabledHTTPHeaderPolicyConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderPolicyConfigRequest) (*pb.FindEnabledHTTPHeaderPolicyConfigResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + config, err := models.SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(req.HeaderPolicyId) + if err != nil { + return nil, err + } + + configData, err := json.Marshal(config) + if err != nil { + return nil, err + } + + return &pb.FindEnabledHTTPHeaderPolicyConfigResponse{Config: configData}, nil +} + +// 创建策略 +func (this *HTTPHeaderPolicyService) CreateHTTPHeaderPolicy(ctx context.Context, req *pb.CreateHTTPHeaderPolicyRequest) (*pb.CreateHTTPHeaderPolicyResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + headerPolicyId, err := models.SharedHTTPHeaderPolicyDAO.CreateHeaderPolicy() + if err != nil { + return nil, err + } + + return &pb.CreateHTTPHeaderPolicyResponse{HeaderPolicyId: headerPolicyId}, nil +} + +// 修改AddHeaders +func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingHeadersRequest) (*pb.UpdateHTTPHeaderPolicyAddingHeadersResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingHeaders(req.HeaderPolicyId, req.HeadersJSON) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderPolicyAddingHeadersResponse{}, nil +} + +// 修改SetHeaders +func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicySettingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicySettingHeadersRequest) (*pb.UpdateHTTPHeaderPolicySettingHeadersResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderPolicyDAO.UpdateSettingHeaders(req.HeaderPolicyId, req.HeadersJSON) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderPolicySettingHeadersResponse{}, nil +} + +// 修改AddTrailers +func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingTrailers(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingTrailersRequest) (*pb.UpdateHTTPHeaderPolicyAddingTrailersResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingTrailers(req.HeaderPolicyId, req.HeadersJSON) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderPolicyAddingTrailersResponse{}, nil +} + +// 修改ReplaceHeaders +func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyReplacingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyReplacingHeadersRequest) (*pb.UpdateHTTPHeaderPolicyReplacingHeadersResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderPolicyDAO.UpdateReplacingHeaders(req.HeaderPolicyId, req.HeadersJSON) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderPolicyReplacingHeadersResponse{}, nil +} + +// 修改删除的Headers +func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyDeletingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest) (*pb.UpdateHTTPHeaderPolicyDeletingHeadersResponse, error) { + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPHeaderPolicyDAO.UpdateDeletingHeaders(req.HeaderPolicyId, req.HeaderNames) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPHeaderPolicyDeletingHeadersResponse{}, nil +} diff --git a/internal/rpc/services/service_http_web.go b/internal/rpc/services/service_http_web.go index 0e093691..8d881bca 100644 --- a/internal/rpc/services/service_http_web.go +++ b/internal/rpc/services/service_http_web.go @@ -48,6 +48,9 @@ func (this *HTTPWebService) FindEnabledHTTPWeb(ctx context.Context, req *pb.Find result.IsOn = web.IsOn == 1 result.Root = web.Root result.GzipId = int64(web.GzipId) + result.Charset = web.Charset + result.RequestHeaderPolicyId = int64(web.RequestHeaderPolicyId) + result.ResponseHeaderPolicyId = int64(web.ResponseHeaderPolicyId) return &pb.FindEnabledHTTPWebResponse{Web: result}, nil } @@ -82,3 +85,51 @@ func (this *HTTPWebService) UpdateHTTPWebGzip(ctx context.Context, req *pb.Updat return &pb.UpdateHTTPWebGzipResponse{}, nil } + +// 修改字符集配置 +func (this *HTTPWebService) UpdateHTTPWebCharset(ctx context.Context, req *pb.UpdateHTTPWebCharsetRequest) (*pb.UpdateHTTPWebCharsetResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPWebDAO.UpdateWebCharset(req.WebId, req.Charset) + if err != nil { + return nil, err + } + return &pb.UpdateHTTPWebCharsetResponse{}, nil +} + +// 更改请求Header策略 +func (this *HTTPWebService) UpdateHTTPWebRequestHeaderPolicy(ctx context.Context, req *pb.UpdateHTTPWebRequestHeaderPolicyRequest) (*pb.UpdateHTTPWebRequestHeaderPolicyResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPWebDAO.UpdateHTTPWebRequestHeaderPolicy(req.WebId, req.HeaderPolicyId) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPWebRequestHeaderPolicyResponse{}, nil +} + +// 更改响应Header策略 +func (this *HTTPWebService) UpdateHTTPWebResponseHeaderPolicy(ctx context.Context, req *pb.UpdateHTTPWebResponseHeaderPolicyRequest) (*pb.UpdateHTTPWebResponseHeaderPolicyResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + err = models.SharedHTTPWebDAO.UpdateHTTPWebResponseHeaderPolicy(req.WebId, req.HeaderPolicyId) + if err != nil { + return nil, err + } + + return &pb.UpdateHTTPWebResponseHeaderPolicyResponse{}, nil + +} diff --git a/internal/rpc/services/service_server.go b/internal/rpc/services/service_server.go index a9299c01..cc66c29d 100644 --- a/internal/rpc/services/service_server.go +++ b/internal/rpc/services/service_server.go @@ -562,16 +562,32 @@ func (this *ServerService) FindServerReverseProxyConfig(ctx context.Context, req } // 初始化Web设置 -func (this *ServerService) InitServerWeb(ctx context.Context, req *pb.InitServerWebRequest) (*pb.InitServerWebResponse, error) { +func (this *ServerService) FindAndInitServerWebConfig(ctx context.Context, req *pb.FindAndInitServerWebRequest) (*pb.FindAndInitServerWebResponse, error) { _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) if err != nil { return nil, err } - webId, err := models.SharedServerDAO.InitServerWeb(req.ServerId) + webId, err := models.SharedServerDAO.FindServerWebId(req.ServerId) if err != nil { return nil, err } - return &pb.InitServerWebResponse{WebId: webId}, nil + if webId == 0 { + webId, err = models.SharedServerDAO.InitServerWeb(req.ServerId) + if err != nil { + return nil, err + } + } + + config, err := models.SharedHTTPWebDAO.ComposeWebConfig(webId) + if err != nil { + return nil, err + } + configJSON, err := json.Marshal(config) + if err != nil { + return nil, err + } + + return &pb.FindAndInitServerWebResponse{Config: configJSON}, nil }