优化文件传输占用内存问题
This commit is contained in:
@@ -9,7 +9,7 @@ Version=$(genVersion $1)
|
|||||||
echo ${Version}
|
echo ${Version}
|
||||||
|
|
||||||
Username="eolinker"
|
Username="eolinker"
|
||||||
if [[ "$1" != "" ]]
|
if [[ "$2" != "" ]]
|
||||||
then
|
then
|
||||||
Username=$2
|
Username=$2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ func (a *additionalParam) Execute(ctx http_service.IHttpContext) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
contentType, _, _ := mime.ParseMediaType(ctx.Proxy().Body().ContentType())
|
contentType, _, _ := mime.ParseMediaType(ctx.Proxy().Body().ContentType())
|
||||||
bodyParams, formParams, err := parseBodyParams(ctx)
|
var bodyParams interface{}
|
||||||
if err != nil {
|
var formParams map[string][]string
|
||||||
return fmt.Errorf(`fail to parse body! [err]: %v`, err)
|
var err error
|
||||||
}
|
|
||||||
for _, p := range a.params {
|
for _, p := range a.params {
|
||||||
conflict := p.Conflict
|
conflict := p.Conflict
|
||||||
if conflict == "" {
|
if conflict == "" {
|
||||||
@@ -45,6 +45,12 @@ func (a *additionalParam) Execute(ctx http_service.IHttpContext) error {
|
|||||||
if ctx.Proxy().Method() != http.MethodPost && ctx.Proxy().Method() != http.MethodPut && ctx.Proxy().Method() != http.MethodPatch {
|
if ctx.Proxy().Method() != http.MethodPost && ctx.Proxy().Method() != http.MethodPut && ctx.Proxy().Method() != http.MethodPatch {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if bodyParams == nil && formParams == nil {
|
||||||
|
bodyParams, formParams, err = parseBodyParams(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(`fail to parse body! [err]: %v`, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
switch contentType {
|
switch contentType {
|
||||||
case http_context.FormData, http_context.MultipartForm:
|
case http_context.FormData, http_context.MultipartForm:
|
||||||
switch p.Conflict {
|
switch p.Conflict {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package http_context
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"github.com/eolinker/eosc/log"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -32,7 +33,8 @@ const (
|
|||||||
type BodyRequestHandler struct {
|
type BodyRequestHandler struct {
|
||||||
request *fasthttp.Request
|
request *fasthttp.Request
|
||||||
|
|
||||||
formdata *multipart.Form
|
formdata *multipart.Form
|
||||||
|
isResetFile bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BodyRequestHandler) MultipartForm() (*multipart.Form, error) {
|
func (b *BodyRequestHandler) MultipartForm() (*multipart.Form, error) {
|
||||||
@@ -52,7 +54,8 @@ func (b *BodyRequestHandler) MultipartForm() (*multipart.Form, error) {
|
|||||||
File: form.File,
|
File: form.File,
|
||||||
}
|
}
|
||||||
|
|
||||||
return form, b.resetFile()
|
//return form, b.resetFile()
|
||||||
|
return form, nil
|
||||||
}
|
}
|
||||||
func (b *BodyRequestHandler) Files() (map[string][]*multipart.FileHeader, error) {
|
func (b *BodyRequestHandler) Files() (map[string][]*multipart.FileHeader, error) {
|
||||||
form, err := b.MultipartForm()
|
form, err := b.MultipartForm()
|
||||||
@@ -121,6 +124,18 @@ func (b *BodyRequestHandler) BodyForm() (url.Values, error) {
|
|||||||
|
|
||||||
// RawBody 获取raw数据
|
// RawBody 获取raw数据
|
||||||
func (b *BodyRequestHandler) RawBody() ([]byte, error) {
|
func (b *BodyRequestHandler) RawBody() ([]byte, error) {
|
||||||
|
if b.isResetFile == false {
|
||||||
|
contentType, _, _ := mime.ParseMediaType(string(b.request.Header.ContentType()))
|
||||||
|
if contentType == MultipartForm {
|
||||||
|
err := b.resetFile()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("reset file error: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b.isResetFile = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return b.request.Body(), nil
|
return b.request.Body(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +163,9 @@ func (b *BodyRequestHandler) SetToForm(key, value string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
multipartForm.Value[key] = []string{value}
|
multipartForm.Value[key] = []string{value}
|
||||||
return b.resetFile()
|
b.isResetFile = false
|
||||||
|
//return b.resetFile()
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return ErrorNotForm
|
return ErrorNotForm
|
||||||
}
|
}
|
||||||
@@ -169,7 +186,9 @@ func (b *BodyRequestHandler) AddForm(key, value string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
multipartForm.Value[key] = append(multipartForm.Value[key], value)
|
multipartForm.Value[key] = append(multipartForm.Value[key], value)
|
||||||
return b.resetFile()
|
b.isResetFile = false
|
||||||
|
//return b.resetFile()
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return ErrorNotForm
|
return ErrorNotForm
|
||||||
}
|
}
|
||||||
@@ -187,8 +206,9 @@ func (b *BodyRequestHandler) AddFile(key string, file *multipart.FileHeader) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
multipartForm.File[key] = append(multipartForm.File[key], file)
|
multipartForm.File[key] = append(multipartForm.File[key], file)
|
||||||
|
b.isResetFile = false
|
||||||
return b.resetFile()
|
//return b.resetFile()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFile 设置文件参数
|
// SetFile 设置文件参数
|
||||||
@@ -200,7 +220,8 @@ func (b *BodyRequestHandler) SetFile(files map[string][]*multipart.FileHeader) e
|
|||||||
}
|
}
|
||||||
multipartForm.File = files
|
multipartForm.File = files
|
||||||
|
|
||||||
return b.resetFile()
|
//return b.resetFile()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BodyRequestHandler) resetFile() error {
|
func (b *BodyRequestHandler) resetFile() error {
|
||||||
@@ -218,11 +239,6 @@ func (b *BodyRequestHandler) resetFile() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//part, err := writer.CreateFormFile(name, f.Filename)
|
|
||||||
//if err != nil {
|
|
||||||
// fio.Close()
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
part, err := writer.CreatePart(f.Header)
|
part, err := writer.CreatePart(f.Header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -279,7 +295,8 @@ func (b *BodyRequestHandler) SetForm(values url.Values) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
multipartForm.Value = values
|
multipartForm.Value = values
|
||||||
return b.resetFile()
|
//return b.resetFile()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorNotForm
|
return ErrorNotForm
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -183,7 +184,7 @@ func (ctx *HttpContext) SendTo(scheme string, node eoscContext.INode, timeout ti
|
|||||||
|
|
||||||
host := node.Addr()
|
host := node.Addr()
|
||||||
request := ctx.proxyRequest.Request()
|
request := ctx.proxyRequest.Request()
|
||||||
request.CloseBodyStream()
|
//request.CloseBodyStream()
|
||||||
rewriteHost := string(request.Host())
|
rewriteHost := string(request.Host())
|
||||||
upstreamHost := ctx.GetUpstreamHostHandler()
|
upstreamHost := ctx.GetUpstreamHostHandler()
|
||||||
if upstreamHost != nil {
|
if upstreamHost != nil {
|
||||||
@@ -203,6 +204,9 @@ func (ctx *HttpContext) SendTo(scheme string, node eoscContext.INode, timeout ti
|
|||||||
rewriteHost = host
|
rewriteHost = host
|
||||||
request.URI().SetHost(host)
|
request.URI().SetHost(host)
|
||||||
}
|
}
|
||||||
|
var m runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&m)
|
||||||
|
log.DebugF("After: HeapAlloc=%.2f MB", float64(m.HeapAlloc)/(1024.0*1024.0))
|
||||||
|
|
||||||
beginTime := time.Now()
|
beginTime := time.Now()
|
||||||
response := fasthttp.AcquireResponse()
|
response := fasthttp.AcquireResponse()
|
||||||
@@ -363,6 +367,9 @@ func (ctx *HttpContext) Clone() (eoscContext.EoContext, error) {
|
|||||||
|
|
||||||
// NewContext 创建Context
|
// NewContext 创建Context
|
||||||
func NewContext(ctx *fasthttp.RequestCtx, port int) *HttpContext {
|
func NewContext(ctx *fasthttp.RequestCtx, port int) *HttpContext {
|
||||||
|
var m runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&m)
|
||||||
|
log.DebugF("Before: HeapAlloc=%.2f MB", float64(m.HeapAlloc)/(1024.0*1024.0))
|
||||||
|
|
||||||
remoteAddr := ctx.RemoteAddr().String()
|
remoteAddr := ctx.RemoteAddr().String()
|
||||||
|
|
||||||
@@ -374,9 +381,9 @@ func NewContext(ctx *fasthttp.RequestCtx, port int) *HttpContext {
|
|||||||
// 原始请求最大读取body为8k,使用clone request
|
// 原始请求最大读取body为8k,使用clone request
|
||||||
request := fasthttp.AcquireRequest()
|
request := fasthttp.AcquireRequest()
|
||||||
|
|
||||||
if ctx.Request.IsBodyStream() && ctx.Request.Header.ContentLength() > 8*1024 {
|
//if ctx.Request.IsBodyStream() && ctx.Request.Header.ContentLength() > 8*1024 {
|
||||||
ctx.Request.Body()
|
// ctx.Request.Body()
|
||||||
}
|
//}
|
||||||
ctx.Request.CopyTo(request)
|
ctx.Request.CopyTo(request)
|
||||||
httpContext.requestReader.reset(request, remoteAddr)
|
httpContext.requestReader.reset(request, remoteAddr)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user