diff --git a/internal/nodes/http_request.go b/internal/nodes/http_request.go index 1bd6896..3018a3c 100644 --- a/internal/nodes/http_request.go +++ b/internal/nodes/http_request.go @@ -1,6 +1,7 @@ package nodes import ( + "bytes" "context" "errors" "fmt" @@ -12,6 +13,7 @@ import ( "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/iwind/TeaGo/types" "io" + "io/ioutil" "net" "net/http" "net/url" @@ -70,7 +72,7 @@ type HTTPRequest struct { cacheKey string // 缓存使用的Key isCached bool // 是否已经被缓存 isAttack bool // 是否是攻击请求 - bodyData []byte // 读取的Body内容 + requestBodyData []byte // 读取的Body内容 // WAF相关 firewallPolicyId int64 @@ -205,6 +207,20 @@ func (this *HTTPRequest) Do() { // 开始调用 func (this *HTTPRequest) doBegin() { + // 处理requestBody + if this.RawReq.ContentLength > 0 && + this.web.AccessLogRef != nil && + this.web.AccessLogRef.IsOn && + this.web.AccessLogRef.ContainsField(serverconfigs.HTTPAccessLogFieldRequestBody) { + var err error + this.requestBodyData, err = ioutil.ReadAll(io.LimitReader(this.RawReq.Body, AccessLogMaxRequestBodySize)) + if err != nil { + this.write50x(err, http.StatusBadGateway) + return + } + this.RawReq.Body = ioutil.NopCloser(io.MultiReader(bytes.NewBuffer(this.requestBodyData), this.RawReq.Body)) + } + // 处理健康检查 var healthCheckKey = this.RawReq.Header.Get(serverconfigs.HealthCheckHeaderName) if len(healthCheckKey) > 0 { diff --git a/internal/nodes/http_request_log.go b/internal/nodes/http_request_log.go index b4bec5a..fa91a9c 100644 --- a/internal/nodes/http_request_log.go +++ b/internal/nodes/http_request_log.go @@ -7,6 +7,11 @@ import ( "time" ) +const ( + // AccessLogMaxRequestBodySize 访问日志存储的请求内容最大尺寸 TODO 此值应该可以在访问日志页设置 + AccessLogMaxRequestBodySize = 2 * 1024 * 1024 +) + // 日志 func (this *HTTPRequest) log() { if this.disableLog { @@ -140,6 +145,15 @@ func (this *HTTPRequest) log() { accessLog.OriginAddress = this.originAddr } + // 请求Body + if ref.ContainsField(serverconfigs.HTTPAccessLogFieldRequestBody) { + accessLog.RequestBody = this.requestBodyData + + if len(accessLog.RequestBody) > AccessLogMaxRequestBodySize { + accessLog.RequestBody = accessLog.RequestBody[:AccessLogMaxRequestBodySize] + } + } + // TODO 记录匹配的 locationId和rewriteId sharedHTTPAccessLogQueue.Push(accessLog) diff --git a/internal/nodes/http_request_waf.go b/internal/nodes/http_request_waf.go index a0ba70a..cecdb1c 100644 --- a/internal/nodes/http_request_waf.go +++ b/internal/nodes/http_request_waf.go @@ -287,12 +287,12 @@ func (this *HTTPRequest) WAFRemoteIP() string { // WAFGetCacheBody 获取缓存中的Body func (this *HTTPRequest) WAFGetCacheBody() []byte { - return this.bodyData + return this.requestBodyData } // WAFSetCacheBody 设置Body func (this *HTTPRequest) WAFSetCacheBody(body []byte) { - this.bodyData = body + this.requestBodyData = body } // WAFReadBody 读取Body @@ -307,10 +307,7 @@ func (this *HTTPRequest) WAFReadBody(max int64) (data []byte, err error) { // WAFRestoreBody 恢复Body func (this *HTTPRequest) WAFRestoreBody(data []byte) { if len(data) > 0 { - rawReader := bytes.NewBuffer(data) - buf := make([]byte, 1024) - _, _ = io.CopyBuffer(rawReader, this.RawReq.Body, buf) - this.RawReq.Body = ioutil.NopCloser(rawReader) + this.RawReq.Body = ioutil.NopCloser(io.MultiReader(bytes.NewBuffer(data), this.RawReq.Body)) } }