1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-01-08 10:45:04 +02:00
imgproxy/transport/fs/fs.go

108 lines
2.1 KiB
Go
Raw Normal View History

2021-04-26 13:52:50 +02:00
package fs
2019-02-04 16:04:19 +02:00
import (
2021-09-29 12:23:54 +02:00
"crypto/md5"
"encoding/base64"
2019-02-04 16:04:19 +02:00
"fmt"
"io"
2021-09-29 12:23:54 +02:00
"io/fs"
2019-02-04 16:04:19 +02:00
"net/http"
"os"
"strings"
2021-04-26 13:52:50 +02:00
2021-09-30 16:23:30 +02:00
"github.com/imgproxy/imgproxy/v3/config"
2019-02-04 16:04:19 +02:00
)
2021-04-26 13:52:50 +02:00
type transport struct {
2019-02-04 16:04:19 +02:00
fs http.Dir
}
2021-04-26 13:52:50 +02:00
func New() transport {
return transport{fs: http.Dir(config.LocalFileSystemRoot)}
2019-02-04 16:04:19 +02:00
}
2021-04-26 13:52:50 +02:00
func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
header := make(http.Header)
2019-02-04 16:04:19 +02:00
f, err := t.fs.Open(req.URL.Path)
2019-02-04 16:04:19 +02:00
if err != nil {
if os.IsNotExist(err) {
return &http.Response{
StatusCode: http.StatusNotFound,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Header: header,
ContentLength: 0,
Body: io.NopCloser(strings.NewReader(
fmt.Sprintf("%s doesn't exist", req.URL.Path),
)),
Close: false,
Request: req,
}, nil
}
2019-02-04 16:04:19 +02:00
return nil, err
}
fi, err := f.Stat()
if err != nil {
return nil, err
}
if fi.IsDir() {
return &http.Response{
StatusCode: http.StatusNotFound,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Header: header,
ContentLength: 0,
Body: io.NopCloser(strings.NewReader(
fmt.Sprintf("%s is directory", req.URL.Path),
)),
Close: false,
Request: req,
}, nil
2019-02-04 16:04:19 +02:00
}
2021-09-29 12:23:54 +02:00
if config.ETagEnabled {
etag := BuildEtag(req.URL.Path, fi)
header.Set("ETag", etag)
if etag == req.Header.Get("If-None-Match") {
2022-04-07 19:32:51 +02:00
f.Close()
2021-09-29 12:23:54 +02:00
return &http.Response{
StatusCode: http.StatusNotModified,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Header: header,
ContentLength: 0,
Body: nil,
Close: false,
Request: req,
}, nil
}
}
2019-02-04 16:04:19 +02:00
return &http.Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
2021-09-29 12:23:54 +02:00
Header: header,
2019-02-04 16:04:19 +02:00
ContentLength: fi.Size(),
Body: f,
Close: true,
Request: req,
}, nil
}
2021-09-29 12:23:54 +02:00
func BuildEtag(path string, fi fs.FileInfo) string {
tag := fmt.Sprintf("%s__%d__%d", path, fi.Size(), fi.ModTime().UnixNano())
hash := md5.Sum([]byte(tag))
return `"` + string(base64.RawURLEncoding.EncodeToString(hash[:])) + `"`
}