diff --git a/internal/caches/reader.go b/internal/caches/reader.go index bee974d..1223a20 100644 --- a/internal/caches/reader.go +++ b/internal/caches/reader.go @@ -12,6 +12,9 @@ type Reader interface { // Status 状态码 Status() int + // LastModified 最后修改时间 + LastModified() int64 + // ReadHeader 读取Header ReadHeader(buf []byte, callback ReaderFunc) error diff --git a/internal/caches/reader_file.go b/internal/caches/reader_file.go index 6c15edc..c77d4f7 100644 --- a/internal/caches/reader_file.go +++ b/internal/caches/reader_file.go @@ -114,6 +114,14 @@ func (this *FileReader) Status() int { 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 { return int64(this.headerSize) } diff --git a/internal/caches/reader_memory.go b/internal/caches/reader_memory.go index 27b416c..7996773 100644 --- a/internal/caches/reader_memory.go +++ b/internal/caches/reader_memory.go @@ -24,6 +24,10 @@ func (this *MemoryReader) Status() int { return this.item.Status } +func (this *MemoryReader) LastModified() int64 { + return this.item.ModifiedAt +} + func (this *MemoryReader) HeaderSize() int64 { return int64(len(this.item.HeaderValue)) } diff --git a/internal/caches/storage_memory.go b/internal/caches/storage_memory.go index 1ad57b0..f037449 100644 --- a/internal/caches/storage_memory.go +++ b/internal/caches/storage_memory.go @@ -19,6 +19,7 @@ type MemoryItem struct { BodyValue []byte Status int IsDone bool + ModifiedAt int64 } func (this *MemoryItem) IsExpired() bool { diff --git a/internal/caches/writer_memory.go b/internal/caches/writer_memory.go index 9de33f1..1b7b51e 100644 --- a/internal/caches/writer_memory.go +++ b/internal/caches/writer_memory.go @@ -3,6 +3,7 @@ package caches import ( "github.com/cespare/xxhash" "sync" + "time" ) type MemoryWriter struct { @@ -26,8 +27,9 @@ func NewMemoryWriter(m map[uint64]*MemoryItem, key string, expiredAt int64, stat expiredAt: expiredAt, locker: locker, item: &MemoryItem{ - ExpiredAt: expiredAt, - Status: status, + ExpiredAt: expiredAt, + ModifiedAt: time.Now().Unix(), + Status: status, }, status: status, endFunc: endFunc, diff --git a/internal/nodes/http_request_cache.go b/internal/nodes/http_request_cache.go index 36c0d24..a07d4ed 100644 --- a/internal/nodes/http_request_cache.go +++ b/internal/nodes/http_request_cache.go @@ -8,6 +8,7 @@ import ( "github.com/iwind/TeaGo/logs" "net/http" "strconv" + "time" ) // 读取缓存 @@ -120,6 +121,7 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) { } defer func() { _ = reader.Close() + this.cacheRef = nil // 终止读取不再往下传递 }() this.varMapping["cache.status"] = "HIT" @@ -156,6 +158,45 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) { if addStatusHeader { 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()) // 输出Body @@ -313,7 +354,6 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) { } } - this.cacheRef = nil // 终止读取不再往下传递 this.isCached = true return true } diff --git a/internal/nodes/http_request_reverse_proxy.go b/internal/nodes/http_request_reverse_proxy.go index 9454093..0e07573 100644 --- a/internal/nodes/http_request_reverse_proxy.go +++ b/internal/nodes/http_request_reverse_proxy.go @@ -162,7 +162,7 @@ func (this *HTTPRequest) doReverseProxy() { // TODO 如果超过最大失败次数,则下线 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 { // 是否为客户端方面的错误 isClientError := false