mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-06 18:10:26 +08:00
缓存支持ETag和Last-Modified
This commit is contained in:
@@ -12,6 +12,9 @@ type Reader interface {
|
|||||||
// Status 状态码
|
// Status 状态码
|
||||||
Status() int
|
Status() int
|
||||||
|
|
||||||
|
// LastModified 最后修改时间
|
||||||
|
LastModified() int64
|
||||||
|
|
||||||
// ReadHeader 读取Header
|
// ReadHeader 读取Header
|
||||||
ReadHeader(buf []byte, callback ReaderFunc) error
|
ReadHeader(buf []byte, callback ReaderFunc) error
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,14 @@ func (this *FileReader) Status() int {
|
|||||||
return this.status
|
return this.status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *FileReader) LastModified() int64 {
|
||||||
|
stat, err := this.fp.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return stat.ModTime().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
func (this *FileReader) HeaderSize() int64 {
|
func (this *FileReader) HeaderSize() int64 {
|
||||||
return int64(this.headerSize)
|
return int64(this.headerSize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ func (this *MemoryReader) Status() int {
|
|||||||
return this.item.Status
|
return this.item.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *MemoryReader) LastModified() int64 {
|
||||||
|
return this.item.ModifiedAt
|
||||||
|
}
|
||||||
|
|
||||||
func (this *MemoryReader) HeaderSize() int64 {
|
func (this *MemoryReader) HeaderSize() int64 {
|
||||||
return int64(len(this.item.HeaderValue))
|
return int64(len(this.item.HeaderValue))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type MemoryItem struct {
|
|||||||
BodyValue []byte
|
BodyValue []byte
|
||||||
Status int
|
Status int
|
||||||
IsDone bool
|
IsDone bool
|
||||||
|
ModifiedAt int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *MemoryItem) IsExpired() bool {
|
func (this *MemoryItem) IsExpired() bool {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package caches
|
|||||||
import (
|
import (
|
||||||
"github.com/cespare/xxhash"
|
"github.com/cespare/xxhash"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MemoryWriter struct {
|
type MemoryWriter struct {
|
||||||
@@ -26,8 +27,9 @@ func NewMemoryWriter(m map[uint64]*MemoryItem, key string, expiredAt int64, stat
|
|||||||
expiredAt: expiredAt,
|
expiredAt: expiredAt,
|
||||||
locker: locker,
|
locker: locker,
|
||||||
item: &MemoryItem{
|
item: &MemoryItem{
|
||||||
ExpiredAt: expiredAt,
|
ExpiredAt: expiredAt,
|
||||||
Status: status,
|
ModifiedAt: time.Now().Unix(),
|
||||||
|
Status: status,
|
||||||
},
|
},
|
||||||
status: status,
|
status: status,
|
||||||
endFunc: endFunc,
|
endFunc: endFunc,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 读取缓存
|
// 读取缓存
|
||||||
@@ -120,6 +121,7 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
|
|||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = reader.Close()
|
_ = reader.Close()
|
||||||
|
this.cacheRef = nil // 终止读取不再往下传递
|
||||||
}()
|
}()
|
||||||
|
|
||||||
this.varMapping["cache.status"] = "HIT"
|
this.varMapping["cache.status"] = "HIT"
|
||||||
@@ -156,6 +158,45 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
|
|||||||
if addStatusHeader {
|
if addStatusHeader {
|
||||||
this.writer.Header().Set("X-Cache", "HIT, "+refType+", "+reader.TypeName())
|
this.writer.Header().Set("X-Cache", "HIT, "+refType+", "+reader.TypeName())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ETag
|
||||||
|
var respHeader = this.writer.Header()
|
||||||
|
var eTag = respHeader.Get("ETag")
|
||||||
|
var lastModifiedAt = reader.LastModified()
|
||||||
|
if len(eTag) == 0 {
|
||||||
|
if lastModifiedAt > 0 {
|
||||||
|
eTag = "\"" + strconv.FormatInt(lastModifiedAt, 10) + "\""
|
||||||
|
respHeader["ETag"] = []string{eTag}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持 Last-Modified
|
||||||
|
var modifiedTime = respHeader.Get("Last-Modified")
|
||||||
|
if len(modifiedTime) == 0 {
|
||||||
|
if lastModifiedAt > 0 {
|
||||||
|
modifiedTime = time.Unix(lastModifiedAt, 0).Format("Mon, 02 Jan 2006 15:04:05 GMT")
|
||||||
|
if len(respHeader.Get("Last-Modified")) == 0 {
|
||||||
|
respHeader.Set("Last-Modified", modifiedTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持 If-None-Match
|
||||||
|
if len(eTag) > 0 && this.requestHeader("If-None-Match") == eTag {
|
||||||
|
// 自定义Header
|
||||||
|
this.processResponseHeaders(http.StatusNotModified)
|
||||||
|
this.writer.WriteHeader(http.StatusNotModified)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持 If-Modified-Since
|
||||||
|
if len(modifiedTime) > 0 && this.requestHeader("If-Modified-Since") == modifiedTime {
|
||||||
|
// 自定义Header
|
||||||
|
this.processResponseHeaders(http.StatusNotModified)
|
||||||
|
this.writer.WriteHeader(http.StatusNotModified)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
this.processResponseHeaders(reader.Status())
|
this.processResponseHeaders(reader.Status())
|
||||||
|
|
||||||
// 输出Body
|
// 输出Body
|
||||||
@@ -313,7 +354,6 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cacheRef = nil // 终止读取不再往下传递
|
|
||||||
this.isCached = true
|
this.isCached = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func (this *HTTPRequest) doReverseProxy() {
|
|||||||
// TODO 如果超过最大失败次数,则下线
|
// TODO 如果超过最大失败次数,则下线
|
||||||
|
|
||||||
this.write502(err)
|
this.write502(err)
|
||||||
remotelogs.Println("HTTP_REQUEST_REVERSE_PROXY", this.RawReq.URL.String()+"': "+err.Error())
|
remotelogs.Warn("HTTP_REQUEST_REVERSE_PROXY", this.RawReq.URL.String()+"': "+err.Error())
|
||||||
} else {
|
} else {
|
||||||
// 是否为客户端方面的错误
|
// 是否为客户端方面的错误
|
||||||
isClientError := false
|
isClientError := false
|
||||||
|
|||||||
Reference in New Issue
Block a user