mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 07:40:56 +08:00 
			
		
		
		
	根据Accept-Encoding决定是否解压响应内容
This commit is contained in:
		@@ -24,6 +24,9 @@ type Reader interface {
 | 
				
			|||||||
	// ReadBody 读取Body
 | 
						// ReadBody 读取Body
 | 
				
			||||||
	ReadBody(buf []byte, callback ReaderFunc) error
 | 
						ReadBody(buf []byte, callback ReaderFunc) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read 实现io.Reader接口
 | 
				
			||||||
 | 
						Read(buf []byte) (int, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ReadBodyRange 读取某个范围内的Body
 | 
						// ReadBodyRange 读取某个范围内的Body
 | 
				
			||||||
	ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error
 | 
						ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -222,6 +222,37 @@ func (this *FileReader) ReadBody(buf []byte, callback ReaderFunc) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *FileReader) Read(buf []byte) (n int, err error) {
 | 
				
			||||||
 | 
						var isOk = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if !isOk {
 | 
				
			||||||
 | 
								_ = this.discard()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 直接返回从Header中剩余的
 | 
				
			||||||
 | 
						if this.bodyBufLen > 0 && len(buf) >= this.bodyBufLen {
 | 
				
			||||||
 | 
							copy(buf, this.bodyBuf)
 | 
				
			||||||
 | 
							isOk = true
 | 
				
			||||||
 | 
							n = this.bodyBufLen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if this.bodySize <= int64(this.bodyBufLen) {
 | 
				
			||||||
 | 
								err = io.EOF
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.bodyBufLen = 0
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n, err = this.fp.Read(buf)
 | 
				
			||||||
 | 
						if err == nil || err == io.EOF {
 | 
				
			||||||
 | 
							isOk = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *FileReader) ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error {
 | 
					func (this *FileReader) ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error {
 | 
				
			||||||
	isOk := false
 | 
						isOk := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,10 +2,13 @@ package caches
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MemoryReader struct {
 | 
					type MemoryReader struct {
 | 
				
			||||||
	item *MemoryItem
 | 
						item *MemoryItem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						offset int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewMemoryReader(item *MemoryItem) *MemoryReader {
 | 
					func NewMemoryReader(item *MemoryItem) *MemoryReader {
 | 
				
			||||||
@@ -111,6 +114,33 @@ func (this *MemoryReader) ReadBody(buf []byte, callback ReaderFunc) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *MemoryReader) Read(buf []byte) (n int, err error) {
 | 
				
			||||||
 | 
						bufLen := len(buf)
 | 
				
			||||||
 | 
						if bufLen == 0 {
 | 
				
			||||||
 | 
							return 0, errors.New("using empty buffer")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bodySize := len(this.item.BodyValue)
 | 
				
			||||||
 | 
						left := bodySize - this.offset
 | 
				
			||||||
 | 
						if bufLen <= left {
 | 
				
			||||||
 | 
							copy(buf, this.item.BodyValue[this.offset:this.offset+bufLen])
 | 
				
			||||||
 | 
							n = bufLen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.offset += bufLen
 | 
				
			||||||
 | 
							if this.offset >= bodySize {
 | 
				
			||||||
 | 
								err = io.EOF
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							copy(buf, this.item.BodyValue[this.offset:])
 | 
				
			||||||
 | 
							n = left
 | 
				
			||||||
 | 
							err = io.EOF
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *MemoryReader) ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error {
 | 
					func (this *MemoryReader) ReadBodyRange(buf []byte, start int64, end int64, callback ReaderFunc) error {
 | 
				
			||||||
	offset := start
 | 
						offset := start
 | 
				
			||||||
	bodySize := int64(len(this.item.BodyValue))
 | 
						bodySize := int64(len(this.item.BodyValue))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ package compressions
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/andybalholm/brotli"
 | 
						"github.com/andybalholm/brotli"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type BrotliReader struct {
 | 
					type BrotliReader struct {
 | 
				
			||||||
@@ -16,7 +17,11 @@ func NewBrotliReader(reader io.Reader) (Reader, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *BrotliReader) Read(p []byte) (n int, err error) {
 | 
					func (this *BrotliReader) Read(p []byte) (n int, err error) {
 | 
				
			||||||
	return this.reader.Read(p)
 | 
						n, err = this.reader.Read(p)
 | 
				
			||||||
 | 
						if err != nil && strings.Contains(err.Error(), "excessive") {
 | 
				
			||||||
 | 
							err = io.EOF
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *BrotliReader) Close() error {
 | 
					func (this *BrotliReader) Close() error {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								internal/js/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								internal/js/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1 +1 @@
 | 
				
			|||||||
*.go
 | 
					*
 | 
				
			||||||
@@ -5,10 +5,12 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/caches"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/caches"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/compressions"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/goman"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/goman"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
@@ -431,16 +433,28 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
 | 
				
			|||||||
				return true
 | 
									return true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else { // 没有Range
 | 
							} else { // 没有Range
 | 
				
			||||||
 | 
								var body io.Reader = reader
 | 
				
			||||||
 | 
								var contentEncoding = this.writer.Header().Get("Content-Encoding")
 | 
				
			||||||
 | 
								if len(contentEncoding) > 0 && !httpAcceptEncoding(this.RawReq.Header.Get("Accept-Encoding"), contentEncoding) {
 | 
				
			||||||
 | 
									decompressReader, err := compressions.NewReader(body, contentEncoding)
 | 
				
			||||||
 | 
									if err == nil {
 | 
				
			||||||
 | 
										body = decompressReader
 | 
				
			||||||
 | 
										defer func() {
 | 
				
			||||||
 | 
											_ = decompressReader.Close()
 | 
				
			||||||
 | 
										}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										this.writer.Header().Del("Content-Encoding")
 | 
				
			||||||
 | 
										this.writer.Header().Del("Content-Length")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.writer.PrepareCompression(reader.BodySize())
 | 
								this.writer.PrepareCompression(reader.BodySize())
 | 
				
			||||||
			this.writer.WriteHeader(reader.Status())
 | 
								this.writer.WriteHeader(reader.Status())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			err = reader.ReadBody(buf, func(n int) (goNext bool, err error) {
 | 
								_, err = io.CopyBuffer(this.writer, body, buf)
 | 
				
			||||||
				_, err = this.writer.Write(buf[:n])
 | 
								if err == io.EOF {
 | 
				
			||||||
				if err != nil {
 | 
									err = nil
 | 
				
			||||||
					return false, errWritingToClient
 | 
								}
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return true, nil
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				this.varMapping["cache.status"] = "MISS"
 | 
									this.varMapping["cache.status"] = "MISS"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/compressions"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
@@ -253,6 +254,24 @@ func (this *HTTPRequest) doReverseProxy() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 解压
 | 
				
			||||||
 | 
						if !resp.Uncompressed {
 | 
				
			||||||
 | 
							var contentEncoding = resp.Header.Get("Content-Encoding")
 | 
				
			||||||
 | 
							if len(contentEncoding) > 0 && !httpAcceptEncoding(this.RawReq.Header.Get("Accept-Encoding"), contentEncoding) {
 | 
				
			||||||
 | 
								reader, err := compressions.NewReader(resp.Body, contentEncoding)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									var body = resp.Body
 | 
				
			||||||
 | 
									defer func() {
 | 
				
			||||||
 | 
										_ = body.Close()
 | 
				
			||||||
 | 
									}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									resp.Body = reader
 | 
				
			||||||
 | 
									resp.Header.Del("Content-Encoding")
 | 
				
			||||||
 | 
									resp.Header.Del("Content-Length")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 响应Header
 | 
						// 响应Header
 | 
				
			||||||
	this.writer.AddHeaders(resp.Header)
 | 
						this.writer.AddHeaders(resp.Header)
 | 
				
			||||||
	this.processResponseHeaders(resp.StatusCode)
 | 
						this.processResponseHeaders(resp.StatusCode)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -153,3 +153,19 @@ func httpRequestNextId() string {
 | 
				
			|||||||
	// timestamp + requestId + nodeId
 | 
						// timestamp + requestId + nodeId
 | 
				
			||||||
	return strconv.FormatInt(unixTime, 10) + teaconst.NodeIdString + strconv.Itoa(int(atomic.AddInt32(&httpRequestId, 1)))
 | 
						return strconv.FormatInt(unixTime, 10) + teaconst.NodeIdString + strconv.Itoa(int(atomic.AddInt32(&httpRequestId, 1)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 检查是否可以接受某个编码
 | 
				
			||||||
 | 
					func httpAcceptEncoding(acceptEncodings string, encoding string) bool {
 | 
				
			||||||
 | 
						var pieces = strings.Split(acceptEncodings, ",")
 | 
				
			||||||
 | 
						for _, piece := range pieces {
 | 
				
			||||||
 | 
							var qualityIndex = strings.Index(piece, ";")
 | 
				
			||||||
 | 
							if qualityIndex >= 0 {
 | 
				
			||||||
 | 
								piece = piece[:qualityIndex]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if strings.TrimSpace(piece) == encoding {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user