mirror of
https://github.com/foomo/gofoomo.git
synced 2025-10-16 12:25:44 +00:00
added proper cache-control
This commit is contained in:
parent
731e6822a4
commit
378fae66c5
@ -35,27 +35,33 @@ func (i *ImageInfo) getHeader(name string) []string {
|
||||
return h
|
||||
}
|
||||
|
||||
type ImageRequestResult struct {
|
||||
Error error
|
||||
Request *ImageRequest
|
||||
}
|
||||
|
||||
type ImageRequest struct {
|
||||
Id string
|
||||
IncomingRequest *http.Request
|
||||
FoomoMediaClientInfoCookie *http.Cookie
|
||||
DoneChannel chan *ImageInfo
|
||||
DoneChannel chan *ImageRequestResult
|
||||
ImageInfo *ImageInfo
|
||||
}
|
||||
|
||||
func NewImageRequest(id string, incomingRequest *http.Request, foomoMediaClientInfoCookie *http.Cookie) *ImageRequest {
|
||||
r := new(ImageRequest)
|
||||
r.Id = id
|
||||
r.DoneChannel = make(chan *ImageInfo)
|
||||
r.DoneChannel = make(chan *ImageRequestResult)
|
||||
r.IncomingRequest = incomingRequest
|
||||
r.FoomoMediaClientInfoCookie = foomoMediaClientInfoCookie
|
||||
return r
|
||||
}
|
||||
|
||||
func (i *ImageRequest) execute(cache *Cache) {
|
||||
func (i *ImageRequest) execute(cache *Cache) error {
|
||||
cache.RequestChannel <- i
|
||||
i.ImageInfo = <-i.DoneChannel
|
||||
|
||||
result := <-i.DoneChannel
|
||||
i.ImageInfo = result.Request.ImageInfo
|
||||
return result.Error
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
@ -83,7 +89,7 @@ func NewCache(f *foomo.Foomo) *Cache {
|
||||
|
||||
func (c *Cache) runLoop() {
|
||||
pendingRequests := make(map[string][]*ImageRequest)
|
||||
doneChannel := make(chan *ImageRequest)
|
||||
doneChannel := make(chan *ImageRequestResult)
|
||||
for {
|
||||
select {
|
||||
case r := <-c.RequestChannel:
|
||||
@ -93,25 +99,33 @@ func (c *Cache) runLoop() {
|
||||
// that is a new one
|
||||
pendingRequests[r.Id] = []*ImageRequest{}
|
||||
go func() {
|
||||
r.ImageInfo = c.getImage(r.IncomingRequest, r.FoomoMediaClientInfoCookie)
|
||||
doneChannel <- r
|
||||
info, err := c.getImage(r.IncomingRequest, r.FoomoMediaClientInfoCookie)
|
||||
r.ImageInfo = info
|
||||
doneChannel <- &ImageRequestResult{
|
||||
Request: r,
|
||||
Error: err,
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
log.Println("hang on")
|
||||
}
|
||||
pendingRequests[r.Id] = append(pendingRequests[r.Id], r)
|
||||
case done := <-doneChannel:
|
||||
requests, _ := pendingRequests[done.Id]
|
||||
case result := <-doneChannel:
|
||||
requests, _ := pendingRequests[result.Request.Id]
|
||||
for _, r := range requests {
|
||||
r.DoneChannel <- done.ImageInfo
|
||||
r.DoneChannel <- &ImageRequestResult{
|
||||
Request: r,
|
||||
Error: result.Error,
|
||||
}
|
||||
}
|
||||
delete(pendingRequests, done.Id)
|
||||
delete(pendingRequests, result.Request.Id)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Cache) Get(request *http.Request, breakPoints []int64) *ImageInfo {
|
||||
func (c *Cache) Get(request *http.Request, breakPoints []int64) (info *ImageInfo, err error) {
|
||||
|
||||
cookie := getFoomoMediaClientInfoCookie(request.Cookies(), breakPoints)
|
||||
key := cookie.String() + ":" + request.URL.Path
|
||||
info, ok := c.Directory[key]
|
||||
@ -123,18 +137,21 @@ func (c *Cache) Get(request *http.Request, breakPoints []int64) *ImageInfo {
|
||||
}
|
||||
if ok == false {
|
||||
imageRequest := NewImageRequest(key, request, cookie)
|
||||
imageRequest.execute(c)
|
||||
err := imageRequest.execute(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info = imageRequest.ImageInfo
|
||||
if len(info.Etag) > 0 {
|
||||
info.Filename = c.Foomo.GetModuleCacheDir("Foomo.Media") + "/img-" + info.Etag
|
||||
if fileExists(info.Filename) {
|
||||
c.Directory[key] = info
|
||||
} else {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return info
|
||||
return info, err
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
@ -152,10 +169,11 @@ func (c *Cache) checkFoomoSessionCookie(res *http.Response) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) getImage(incomingRequest *http.Request, foomoMediaClientInfoCookie *http.Cookie) *ImageInfo {
|
||||
func (c *Cache) getImage(incomingRequest *http.Request, foomoMediaClientInfoCookie *http.Cookie) (i *ImageInfo, err error) {
|
||||
request, err := http.NewRequest("HEAD", incomingRequest.URL.String(), nil)
|
||||
|
||||
if err != nil {
|
||||
return NewImageInfo(nil)
|
||||
return NewImageInfo(nil), err
|
||||
} else {
|
||||
request.AddCookie(foomoMediaClientInfoCookie)
|
||||
if c.foomoSessionCookie != nil {
|
||||
@ -171,11 +189,12 @@ func (c *Cache) getImage(incomingRequest *http.Request, foomoMediaClientInfoCook
|
||||
}
|
||||
if err != nil {
|
||||
if imageServerResponse != nil && imageServerResponse.StatusCode == http.StatusMovedPermanently {
|
||||
panic(errors.New("unexpected redirect"))
|
||||
return nil, errors.New("unexpected redirect")
|
||||
} else {
|
||||
panic(errors.New("unexpected error " + err.Error()))
|
||||
return nil, errors.New("unexpected error " + err.Error())
|
||||
}
|
||||
} else {
|
||||
|
||||
i.StatusCode = imageServerResponse.StatusCode
|
||||
c.checkFoomoSessionCookie(imageServerResponse)
|
||||
switch i.StatusCode {
|
||||
@ -193,10 +212,11 @@ func (c *Cache) getImage(incomingRequest *http.Request, foomoMediaClientInfoCook
|
||||
} else {
|
||||
i.Etag = imageServerResponse.Header.Get("Etag")
|
||||
}
|
||||
|
||||
default:
|
||||
panic(errors.New("unexpected reply with status " + imageServerResponse.Status))
|
||||
return nil, errors.New("unexpected reply with status " + imageServerResponse.Status)
|
||||
}
|
||||
}
|
||||
return i
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,10 @@ type SessionConfig struct {
|
||||
func getBreakPoints(f *foomo.Foomo) []int64 {
|
||||
c := &MediaServerConfig{}
|
||||
|
||||
core.GetConfig(f, &c, "Foomo.Media", "Foomo.Media.Image.server", "")
|
||||
err := core.GetConfig(f, &c, "Foomo.Media", "Foomo.Media.Image.server", "")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
breakPointsInt := []int{}
|
||||
|
||||
for breakPointString, _ := range c.Grid {
|
||||
|
||||
@ -3,6 +3,7 @@ package images
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -51,6 +52,7 @@ func readFoomoMediaClientInfo(cookie string) (clientInfo *ClientInfo, err error)
|
||||
|
||||
func clampScreenWidthToGrid(screenWidth int64, breakPoints []int64) int64 {
|
||||
// the last breakpoint
|
||||
log.Println("clampScreenWidthToGrid", screenWidth, breakPoints)
|
||||
distance := breakPoints[len(breakPoints)-1]
|
||||
clampedValue := distance
|
||||
for _, breakPoint := range breakPoints {
|
||||
|
||||
@ -3,11 +3,10 @@ package images
|
||||
import (
|
||||
"errors"
|
||||
"github.com/foomo/gofoomo/foomo"
|
||||
"io"
|
||||
//"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Adaptive struct {
|
||||
@ -34,29 +33,46 @@ func (a *Adaptive) HandlesRequest(incomingRequest *http.Request) bool {
|
||||
}
|
||||
|
||||
func (a *Adaptive) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
|
||||
info := a.Cache.Get(incomingRequest, a.BreakPoints)
|
||||
|
||||
info, err := a.Cache.Get(incomingRequest, a.BreakPoints)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if info == nil {
|
||||
panic(errors.New("could not get image"))
|
||||
} else {
|
||||
// 304
|
||||
|
||||
browserEtag := incomingRequest.Header.Get("If-None-Match")
|
||||
|
||||
if browserEtag == info.Etag {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
writeHeaders(w, info)
|
||||
} else {
|
||||
writeHeaders(w, info)
|
||||
file, err := os.Open(info.Filename)
|
||||
if err != nil {
|
||||
// dummy image ?!
|
||||
panic(errors.New("could not open image file " + info.Filename + " " + err.Error()))
|
||||
} else {
|
||||
io.Copy(w, file)
|
||||
defer file.Close()
|
||||
|
||||
}
|
||||
// 304 handling
|
||||
file, err := os.Open(info.Filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
fileInfo, err := file.Stat()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Header().Set("Expires", time.Now().Add(time.Hour*24*30).Format(http.TimeFormat))
|
||||
//writeHeaders(w, info)
|
||||
http.ServeContent(w, incomingRequest, file.Name(), fileInfo.ModTime(), file)
|
||||
/*
|
||||
browserEtag := incomingRequest.Header.Get("If-None-Match")
|
||||
|
||||
if browserEtag == info.Etag {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
writeHeaders(w, info)
|
||||
} else {
|
||||
writeHeaders(w, info)
|
||||
file, err := os.Open(info.Filename)
|
||||
if err != nil {
|
||||
// dummy image ?!
|
||||
panic(errors.New("could not open image file " + info.Filename + " " + err.Error()))
|
||||
} else {
|
||||
io.Copy(w, file)
|
||||
defer file.Close()
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +81,12 @@ func writeHeaders(w http.ResponseWriter, info *ImageInfo) {
|
||||
if key == "Set-Cookie" {
|
||||
continue
|
||||
}
|
||||
|
||||
/*if key == "Expires" {
|
||||
//force browser cache for 1 year
|
||||
w.Header().Add(key, time.Now().Add(time.Hour*24*365).Format(http.TimeFormat))
|
||||
|
||||
}*/
|
||||
for _, value := range values {
|
||||
w.Header().Add(key, value)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user