add capability to serve with nginx

This commit is contained in:
guochao 2024-12-18 17:16:55 +08:00
parent 1e63315634
commit da78e79dcd
2 changed files with 47 additions and 5 deletions

View File

@ -10,6 +10,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings"
"sync" "sync"
"time" "time"
@ -48,9 +49,15 @@ type LocalStorage struct {
Path string `yaml:"path"` Path string `yaml:"path"`
} }
type Accel struct {
EnableByHeader string `yaml:"enable-by-header"`
ResponseWithHeaders []string `yaml:"response-with-headers"`
}
type Storage struct { type Storage struct {
Type string `yaml:"type"` Type string `yaml:"type"`
Local *LocalStorage `yaml:"local"` Local *LocalStorage `yaml:"local"`
Accel Accel `yaml:"accel"`
} }
type Cache struct { type Cache struct {
@ -146,6 +153,9 @@ func configFromFile(path string) (*Config, error) {
Local: &LocalStorage{ Local: &LocalStorage{
Path: "./data", Path: "./data",
}, },
Accel: Accel{
ResponseWithHeaders: []string{"X-Sendfile", "X-Accel-Redirect"},
},
}, },
Misc: MiscConfig{ Misc: MiscConfig{
FirstChunkBytes: 1024 * 1024 * 50, FirstChunkBytes: 1024 * 1024 * 50,
@ -171,6 +181,24 @@ func configFromFile(path string) (*Config, error) {
return config, nil return config, nil
} }
func (server *Server) serveFile(w http.ResponseWriter, r *http.Request, path string) {
if location := r.Header.Get(server.Storage.Accel.EnableByHeader); server.Storage.Accel.EnableByHeader != "" && location != "" {
relPath, err := filepath.Rel(server.Storage.Local.Path, path)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
accelPath := filepath.Join(location, relPath)
for _, headerKey := range server.Storage.Accel.ResponseWithHeaders {
w.Header().Set(headerKey, accelPath)
}
return
}
http.ServeFile(w, r, path)
}
func (server *Server) handleRequest(w http.ResponseWriter, r *http.Request) { func (server *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
fullpath := filepath.Join(server.Storage.Local.Path, r.URL.Path) fullpath := filepath.Join(server.Storage.Local.Path, r.URL.Path)
fullpath, err := filepath.Abs(fullpath) fullpath, err := filepath.Abs(fullpath)
@ -194,17 +222,17 @@ func (server *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
if localStatus == localExistsButNeedHead { if localStatus == localExistsButNeedHead {
if ranged { if ranged {
server.streamOnline(nil, r, mtime, fullpath) server.streamOnline(nil, r, mtime, fullpath)
http.ServeFile(w, r, fullpath) server.serveFile(w, r, fullpath)
} else { } else {
server.streamOnline(w, r, mtime, fullpath) server.streamOnline(w, r, mtime, fullpath)
} }
} else { } else {
http.ServeFile(w, r, fullpath) server.serveFile(w, r, fullpath)
} }
} else { } else {
if ranged { if ranged {
server.streamOnline(nil, r, mtime, fullpath) server.streamOnline(nil, r, mtime, fullpath)
http.ServeFile(w, r, fullpath) server.serveFile(w, r, fullpath)
} else { } else {
server.streamOnline(w, r, mtime, fullpath) server.streamOnline(w, r, mtime, fullpath)
} }
@ -274,7 +302,7 @@ func (server *Server) streamOnline(w http.ResponseWriter, r *http.Request, mtime
if chunks == nil && mtime != zeroTime { if chunks == nil && mtime != zeroTime {
logrus.WithFields(logrus.Fields{"upstreamIdx": selectedIdx, "key": key}).Trace("not modified. using local version") logrus.WithFields(logrus.Fields{"upstreamIdx": selectedIdx, "key": key}).Trace("not modified. using local version")
if w != nil { if w != nil {
http.ServeFile(w, r, key) server.serveFile(w, r, key)
} }
return return
} }
@ -292,7 +320,7 @@ func (server *Server) streamOnline(w http.ResponseWriter, r *http.Request, mtime
if response.StatusCode == http.StatusNotModified { if response.StatusCode == http.StatusNotModified {
logrus.WithField("upstreamIdx", selectedIdx).Trace("not modified. using local version") logrus.WithField("upstreamIdx", selectedIdx).Trace("not modified. using local version")
os.Chtimes(key, zeroTime, time.Now()) os.Chtimes(key, zeroTime, time.Now())
http.ServeFile(w, r, key) server.serveFile(w, r, key)
return return
} }

View File

@ -44,3 +44,17 @@ storage:
type: local # ignored type: local # ignored
local: local:
path: /data # defaults to ./data path: /data # defaults to ./data
accel:
# example nginx config:
## location /i {
## internal;
## alias /path/to/data;
## }
## location / {
## proxy_pass 127.0.0.1:8881;
## proxy_set_header X-Accel-Path /i;
## }
##
# enable-by-header: "X-Accel-Path"