Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/staticpages/servefile.go')
-rw-r--r--workhorse/internal/staticpages/servefile.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/workhorse/internal/staticpages/servefile.go b/workhorse/internal/staticpages/servefile.go
new file mode 100644
index 00000000000..c98bc030bc2
--- /dev/null
+++ b/workhorse/internal/staticpages/servefile.go
@@ -0,0 +1,84 @@
+package staticpages
+
+import (
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "gitlab.com/gitlab-org/labkit/log"
+ "gitlab.com/gitlab-org/labkit/mask"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/urlprefix"
+)
+
+type CacheMode int
+
+const (
+ CacheDisabled CacheMode = iota
+ CacheExpireMax
+)
+
+// BUG/QUIRK: If a client requests 'foo%2Fbar' and 'foo/bar' exists,
+// handleServeFile will serve foo/bar instead of passing the request
+// upstream.
+func (s *Static) ServeExisting(prefix urlprefix.Prefix, cache CacheMode, notFoundHandler http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ file := filepath.Join(s.DocumentRoot, prefix.Strip(r.URL.Path))
+
+ // The filepath.Join does Clean traversing directories up
+ if !strings.HasPrefix(file, s.DocumentRoot) {
+ helper.Fail500(w, r, &os.PathError{
+ Op: "open",
+ Path: file,
+ Err: os.ErrInvalid,
+ })
+ return
+ }
+
+ var content *os.File
+ var fi os.FileInfo
+ var err error
+
+ // Serve pre-gzipped assets
+ if acceptEncoding := r.Header.Get("Accept-Encoding"); strings.Contains(acceptEncoding, "gzip") {
+ content, fi, err = helper.OpenFile(file + ".gz")
+ if err == nil {
+ w.Header().Set("Content-Encoding", "gzip")
+ }
+ }
+
+ // If not found, open the original file
+ if content == nil || err != nil {
+ content, fi, err = helper.OpenFile(file)
+ }
+ if err != nil {
+ if notFoundHandler != nil {
+ notFoundHandler.ServeHTTP(w, r)
+ } else {
+ http.NotFound(w, r)
+ }
+ return
+ }
+ defer content.Close()
+
+ switch cache {
+ case CacheExpireMax:
+ // Cache statically served files for 1 year
+ cacheUntil := time.Now().AddDate(1, 0, 0).Format(http.TimeFormat)
+ w.Header().Set("Cache-Control", "public")
+ w.Header().Set("Expires", cacheUntil)
+ }
+
+ log.WithContextFields(r.Context(), log.Fields{
+ "file": file,
+ "encoding": w.Header().Get("Content-Encoding"),
+ "method": r.Method,
+ "uri": mask.URL(r.RequestURI),
+ }).Info("Send static file")
+
+ http.ServeContent(w, r, filepath.Base(file), fi.ModTime(), content)
+ })
+}