mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 07:40:56 +08:00 
			
		
		
		
	Partial Content从源站读取数据时验证本地缓存的Content-MD5是否一致
This commit is contained in:
		@@ -12,16 +12,17 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// PartialRanges 内容分区范围定义
 | 
					// PartialRanges 内容分区范围定义
 | 
				
			||||||
type PartialRanges struct {
 | 
					type PartialRanges struct {
 | 
				
			||||||
	Version  int        `json:"version"`  // 版本号
 | 
						Version    int        `json:"version"`    // 版本号
 | 
				
			||||||
	Ranges   [][2]int64 `json:"ranges"`   // 范围
 | 
						Ranges     [][2]int64 `json:"ranges"`     // 范围
 | 
				
			||||||
	BodySize int64      `json:"bodySize"` // 总长度
 | 
						BodySize   int64      `json:"bodySize"`   // 总长度
 | 
				
			||||||
 | 
						ContentMD5 string     `json:"contentMD5"` // 内容md5
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewPartialRanges 获取新对象
 | 
					// NewPartialRanges 获取新对象
 | 
				
			||||||
func NewPartialRanges(expiresAt int64) *PartialRanges {
 | 
					func NewPartialRanges(expiresAt int64) *PartialRanges {
 | 
				
			||||||
	return &PartialRanges{
 | 
						return &PartialRanges{
 | 
				
			||||||
		Ranges:  [][2]int64{},
 | 
							Ranges:  [][2]int64{},
 | 
				
			||||||
		Version: 1,
 | 
							Version: 2,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,6 +47,8 @@ func NewPartialRangesFromData(data []byte) (*PartialRanges, error) {
 | 
				
			|||||||
				if commaIndex > 0 {
 | 
									if commaIndex > 0 {
 | 
				
			||||||
					rs.Ranges = append(rs.Ranges, [2]int64{types.Int64(line[colonIndex+1 : commaIndex]), types.Int64(line[commaIndex+1:])})
 | 
										rs.Ranges = append(rs.Ranges, [2]int64{types.Int64(line[colonIndex+1 : commaIndex]), types.Int64(line[commaIndex+1:])})
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								case "m": // Content-MD5
 | 
				
			||||||
 | 
									rs.ContentMD5 = string(line[colonIndex+1:])
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		data = data[index+1:]
 | 
							data = data[index+1:]
 | 
				
			||||||
@@ -171,6 +174,9 @@ func (this *PartialRanges) FindRangeAtPosition(position int64) (r rangeutils.Ran
 | 
				
			|||||||
func (this *PartialRanges) String() string {
 | 
					func (this *PartialRanges) String() string {
 | 
				
			||||||
	var s = "v:" + strconv.Itoa(this.Version) + "\n" + // version
 | 
						var s = "v:" + strconv.Itoa(this.Version) + "\n" + // version
 | 
				
			||||||
		"b:" + this.formatInt64(this.BodySize) + "\n" // bodySize
 | 
							"b:" + this.formatInt64(this.BodySize) + "\n" // bodySize
 | 
				
			||||||
 | 
						if len(this.ContentMD5) > 0 {
 | 
				
			||||||
 | 
							s += "m:" + this.ContentMD5 + "\n" // Content-MD5
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, r := range this.Ranges {
 | 
						for _, r := range this.Ranges {
 | 
				
			||||||
		s += "r:" + this.formatInt64(r[0]) + "," + this.formatInt64(r[1]) + "\n" // range
 | 
							s += "r:" + this.formatInt64(r[0]) + "," + this.formatInt64(r[1]) + "\n" // range
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,8 @@
 | 
				
			|||||||
package caches_test
 | 
					package caches_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/md5"
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/caches"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/caches"
 | 
				
			||||||
	"github.com/iwind/TeaGo/assert"
 | 
						"github.com/iwind/TeaGo/assert"
 | 
				
			||||||
@@ -167,8 +169,13 @@ func TestPartialRanges_Encode_String(t *testing.T) {
 | 
				
			|||||||
	for i := 0; i < 10; i++ {
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
		r.Ranges = append(r.Ranges, [2]int64{int64(i * 100), int64(i*100 + 100)})
 | 
							r.Ranges = append(r.Ranges, [2]int64{int64(i * 100), int64(i*100 + 100)})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var sum = md5.Sum([]byte("123456"))
 | 
				
			||||||
 | 
						r.ContentMD5 = base64.StdEncoding.EncodeToString(sum[:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var before = time.Now()
 | 
						var before = time.Now()
 | 
				
			||||||
	var data = r.String()
 | 
						var data = r.String()
 | 
				
			||||||
 | 
						t.Log(data)
 | 
				
			||||||
	t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
						t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
				
			||||||
	t.Log(len(data))
 | 
						t.Log(len(data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package caches
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
						fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
 | 
				
			||||||
	"github.com/iwind/TeaGo/Tea"
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
@@ -36,7 +37,7 @@ func TestFileReader(t *testing.T) {
 | 
				
			|||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		_ = fp.Close()
 | 
							_ = fp.Close()
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	reader := NewFileReader(fp)
 | 
						reader := NewFileReader(fsutils.NewFile(fp, fsutils.FlagRead))
 | 
				
			||||||
	err = reader.Init()
 | 
						err = reader.Init()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
@@ -75,7 +76,7 @@ func TestFileReader_ReadHeader(t *testing.T) {
 | 
				
			|||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		_ = fp.Close()
 | 
							_ = fp.Close()
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	var reader = NewFileReader(fp)
 | 
						var reader = NewFileReader(fsutils.NewFile(fp, fsutils.FlagRead))
 | 
				
			||||||
	err = reader.Init()
 | 
						err = reader.Init()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if os.IsNotExist(err) {
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
@@ -138,7 +139,7 @@ func TestFileReader_Range(t *testing.T) {
 | 
				
			|||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		_ = fp.Close()
 | 
							_ = fp.Close()
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	reader := NewFileReader(fp)
 | 
						reader := NewFileReader(fsutils.NewFile(fp, fsutils.FlagRead))
 | 
				
			||||||
	err = reader.Init()
 | 
						err = reader.Init()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
 | 
						fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
 | 
				
			||||||
	"github.com/iwind/TeaGo/types"
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -183,6 +184,14 @@ func (this *PartialFileWriter) SetBodyLength(bodyLength int64) {
 | 
				
			|||||||
	this.bodySize = bodyLength
 | 
						this.bodySize = bodyLength
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetContentMD5 设置内容MD5
 | 
				
			||||||
 | 
					func (this *PartialFileWriter) SetContentMD5(contentMD5 string) {
 | 
				
			||||||
 | 
						if strings.Contains(contentMD5, "\n") || len(contentMD5) > 128 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.ranges.ContentMD5 = contentMD5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WriteBodyLength 写入Body长度数据
 | 
					// WriteBodyLength 写入Body长度数据
 | 
				
			||||||
func (this *PartialFileWriter) WriteBodyLength(bodyLength int64) error {
 | 
					func (this *PartialFileWriter) WriteBodyLength(bodyLength int64) error {
 | 
				
			||||||
	if this.metaBodySize > 0 && this.metaBodySize == bodyLength {
 | 
						if this.metaBodySize > 0 && this.metaBodySize == bodyLength {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ func TestPartialFileWriter_Write(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var ranges = caches.NewPartialRanges(0)
 | 
						var ranges = caches.NewPartialRanges(0)
 | 
				
			||||||
	var writer = caches.NewPartialFileWriter(fp, "test", time.Now().Unix()+86500, -1, -1, true, true, 0, ranges, func() {
 | 
						var writer = caches.NewPartialFileWriter(fsutils.NewFile(fp, fsutils.FlagWrite), "test", time.Now().Unix()+86500, -1, -1, true, true, 0, ranges, func() {
 | 
				
			||||||
		t.Log("end")
 | 
							t.Log("end")
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	_, err = writer.WriteHeader([]byte("header"))
 | 
						_, err = writer.WriteHeader([]byte("header"))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,8 +42,25 @@ func (this *HTTPRequestPartialReader) Read(p []byte) (n int, err error) {
 | 
				
			|||||||
			err = io.ErrUnexpectedEOF
 | 
								err = io.ErrUnexpectedEOF
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.resp = resp
 | 
							this.resp = resp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 对比Content-MD5
 | 
				
			||||||
 | 
							partialReader, ok := this.cacheReader.(*caches.PartialFileReader)
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								if partialReader.Ranges().Version >= 2 && resp.Header.Get("Content-MD5") != partialReader.Ranges().ContentMD5 {
 | 
				
			||||||
 | 
									err = io.ErrUnexpectedEOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var storage = this.req.writer.cacheStorage
 | 
				
			||||||
 | 
									if storage != nil {
 | 
				
			||||||
 | 
										_ = storage.Delete(this.req.cacheKey + caches.SuffixPartial)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 准备写入
 | 
				
			||||||
		this.prepareCacheWriter()
 | 
							this.prepareCacheWriter()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -403,6 +403,11 @@ func (this *HTTPWriter) PrepareCache(resp *http.Response, size int64) {
 | 
				
			|||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				partialWriter.SetBodyLength(total)
 | 
									partialWriter.SetBodyLength(total)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var contentMD5 = this.rawWriter.Header().Get("Content-MD5")
 | 
				
			||||||
 | 
									if len(contentMD5) > 0 {
 | 
				
			||||||
 | 
										partialWriter.SetContentMD5(contentMD5)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var filterReader = readers.NewFilterReaderCloser(resp.Body)
 | 
								var filterReader = readers.NewFilterReaderCloser(resp.Body)
 | 
				
			||||||
			this.cacheIsFinished = true
 | 
								this.cacheIsFinished = true
 | 
				
			||||||
@@ -462,6 +467,11 @@ func (this *HTTPWriter) PrepareCache(resp *http.Response, size int64) {
 | 
				
			|||||||
				// 写入total
 | 
									// 写入total
 | 
				
			||||||
				if !writtenTotal && total > 0 {
 | 
									if !writtenTotal && total > 0 {
 | 
				
			||||||
					partialWriter.SetBodyLength(total)
 | 
										partialWriter.SetBodyLength(total)
 | 
				
			||||||
 | 
										var contentMD5 = this.rawWriter.Header().Get("Content-MD5")
 | 
				
			||||||
 | 
										if len(contentMD5) > 0 {
 | 
				
			||||||
 | 
											partialWriter.SetContentMD5(contentMD5)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					writtenTotal = true
 | 
										writtenTotal = true
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user