mirror of
https://codeberg.org/Codeberg/pages-server.git
synced 2025-05-12 13:07:50 +00:00
Implement static serving of compressed files
This commit is contained in:
parent
e5320e1972
commit
1c0ce28d8e
4 changed files with 154 additions and 20 deletions
|
@ -1,10 +1,13 @@
|
|||
package upstream
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -19,6 +22,8 @@ import (
|
|||
const (
|
||||
headerLastModified = "Last-Modified"
|
||||
headerIfModifiedSince = "If-Modified-Since"
|
||||
headerAcceptEncoding = "Accept-Encoding"
|
||||
headerContentEncoding = "Content-Encoding"
|
||||
|
||||
rawMime = "text/plain; charset=utf-8"
|
||||
)
|
||||
|
@ -52,6 +57,73 @@ type Options struct {
|
|||
ServeRaw bool
|
||||
}
|
||||
|
||||
// allowed encodings
|
||||
var allowedEncodings = map[string]string{
|
||||
"gzip": ".gz",
|
||||
"br": ".br",
|
||||
"zstd": ".zst",
|
||||
"identity": "",
|
||||
}
|
||||
|
||||
// parses Accept-Encoding header into a list of acceptable encodings
|
||||
func AcceptEncodings(header string) []string {
|
||||
log.Trace().Msgf("got accept-encoding: %s", header)
|
||||
encodings := []string{}
|
||||
globQuality := 0.0
|
||||
qualities := make(map[string]float64)
|
||||
|
||||
for _, encoding := range strings.Split(header, ",") {
|
||||
splits := strings.SplitN(encoding, ";q=", 2)
|
||||
name := splits[0]
|
||||
quality := 1.0
|
||||
|
||||
if len(splits) > 1 {
|
||||
var err error
|
||||
quality, err = strconv.ParseFloat(splits[1], 64)
|
||||
if err != nil || quality < 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
name = strings.TrimSpace(name)
|
||||
|
||||
if name == "*" {
|
||||
globQuality = quality
|
||||
} else {
|
||||
_, allowed := allowedEncodings[name]
|
||||
if allowed {
|
||||
qualities[name] = quality
|
||||
if quality > 0 {
|
||||
encodings = append(encodings, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if globQuality > 0 {
|
||||
for encoding := range allowedEncodings {
|
||||
_, exists := qualities[encoding]
|
||||
if !exists {
|
||||
encodings = append(encodings, encoding)
|
||||
qualities[encoding] = globQuality
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, exists := qualities["identity"]
|
||||
if !exists {
|
||||
encodings = append(encodings, "identity")
|
||||
qualities["identity"] = -1
|
||||
}
|
||||
}
|
||||
|
||||
slices.SortStableFunc(encodings, func(x, y string) int {
|
||||
// sort in reverse order; big quality comes first
|
||||
return cmp.Compare(qualities[y], qualities[x])
|
||||
})
|
||||
log.Trace().Msgf("decided encoding order: %#v", encodings)
|
||||
return encodings
|
||||
}
|
||||
|
||||
// Upstream requests a file from the Gitea API at GiteaRoot and writes it to the request context.
|
||||
func (o *Options) Upstream(ctx *context.Context, giteaClient *gitea.Client, redirectsCache cache.ICache) bool {
|
||||
log := log.With().Strs("upstream", []string{o.TargetOwner, o.TargetRepo, o.TargetBranch, o.TargetPath}).Logger()
|
||||
|
@ -97,9 +169,33 @@ func (o *Options) Upstream(ctx *context.Context, giteaClient *gitea.Client, redi
|
|||
|
||||
log.Debug().Msg("Preparing")
|
||||
|
||||
reader, header, statusCode, err := giteaClient.ServeRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, o.TargetPath)
|
||||
if reader != nil {
|
||||
defer reader.Close()
|
||||
var reader io.ReadCloser
|
||||
var header http.Header
|
||||
var statusCode int
|
||||
var err error
|
||||
|
||||
// pick first non-404 response for encoding, *only* if not root
|
||||
if o.TargetPath == "" || strings.HasSuffix(o.TargetPath, "/") {
|
||||
err = gitea.ErrorNotFound
|
||||
} else {
|
||||
for _, encoding := range AcceptEncodings(ctx.Req.Header.Get(headerAcceptEncoding)) {
|
||||
log.Trace().Msgf("try %s encoding", encoding)
|
||||
|
||||
// add extension for encoding
|
||||
path := o.TargetPath + allowedEncodings[encoding]
|
||||
reader, header, statusCode, err = giteaClient.ServeRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, path, true)
|
||||
if statusCode == 404 {
|
||||
continue
|
||||
}
|
||||
log.Debug().Msgf("using %s encoding", encoding)
|
||||
if encoding != "identity" {
|
||||
header.Set(headerContentEncoding, encoding)
|
||||
}
|
||||
break
|
||||
}
|
||||
if reader != nil {
|
||||
defer reader.Close()
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug().Msg("Aquisting")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue