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

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2020-08-20 18:31:30 +0300
committerKamil Trzciński <ayufan@ayufan.eu>2020-08-21 11:32:06 +0300
commitf59aec9d526f05bde08f5c90cc4a1c4c1d8766eb (patch)
treeb7a1d8562e54a62261390f14d6f6bd99fea44863 /internal/vfs/zip/http_range/resource.go
parent71a39de011a7b2d19470c32ed8f73afc372636bf (diff)
Refactor ZIP support to be more OOMzip-using-vfs
Diffstat (limited to 'internal/vfs/zip/http_range/resource.go')
-rw-r--r--internal/vfs/zip/http_range/resource.go70
1 files changed, 70 insertions, 0 deletions
diff --git a/internal/vfs/zip/http_range/resource.go b/internal/vfs/zip/http_range/resource.go
new file mode 100644
index 00000000..d35563b0
--- /dev/null
+++ b/internal/vfs/zip/http_range/resource.go
@@ -0,0 +1,70 @@
+package http_range
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+type Resource struct {
+ URL string
+ Etag string
+ LastModified string
+ Size int64
+}
+
+func NewResource(ctx context.Context, URL string) (*Resource, error) {
+ // the `h.URL` is likely presigned only for GET
+ req, err := http.NewRequest("GET", URL, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ req = req.WithContext(ctx)
+
+ // we fetch a single byte and ensure that range requests is additionally supported
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", 0, 0))
+ res, err := httpClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer io.Copy(ioutil.Discard, res.Body)
+ defer res.Body.Close()
+
+ resource := &Resource{
+ URL: URL,
+ Etag: res.Header.Get("ETag"),
+ LastModified: res.Header.Get("Last-Modified"),
+ }
+
+ switch res.StatusCode {
+ case http.StatusOK:
+ resource.Size = res.ContentLength
+ println(resource.URL, resource.Etag, resource.LastModified, resource.Size)
+ return resource, nil
+
+ case http.StatusPartialContent:
+ contentRange := res.Header.Get("Content-Range")
+ ranges := strings.SplitN(contentRange, "/", 2)
+ if len(ranges) != 2 {
+ return nil, fmt.Errorf("invalid `Content-Range`: %q", contentRange)
+ }
+
+ resource.Size, err = strconv.ParseInt(ranges[1], 0, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ return resource, nil
+
+ case http.StatusRequestedRangeNotSatisfiable:
+ return nil, ErrRangeRequestsNotSupported
+
+ default:
+ return nil, fmt.Errorf("failed with %d: %q", res.StatusCode, res.Status)
+ }
+}