Skip to content

Commit

Permalink
Torrent: Ranged requests so torrents work
Browse files Browse the repository at this point in the history
  • Loading branch information
andreimarcu committed Mar 19, 2020
1 parent 3167ab7 commit 9f7e6b6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 8 deletions.
13 changes: 13 additions & 0 deletions backends/localfs/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"time"
Expand Down Expand Up @@ -82,6 +83,18 @@ func (b LocalfsBackend) Get(key string) (metadata backends.Metadata, f io.ReadCl
return
}

func (b LocalfsBackend) ServeFile(key string, w http.ResponseWriter, r *http.Request) (err error) {
_, err = b.Head(key)
if err != nil {
return
}

filePath := path.Join(b.filesPath, key)
http.ServeFile(w, r, filePath)

return
}

func (b LocalfsBackend) writeMetadata(key string, metadata backends.Metadata) error {
metaPath := path.Join(b.metaPath, key)

Expand Down
38 changes: 38 additions & 0 deletions backends/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package s3
import (
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
Expand Down Expand Up @@ -79,6 +80,43 @@ func (b S3Backend) Get(key string) (metadata backends.Metadata, r io.ReadCloser,
return
}

func (b S3Backend) ServeFile(key string, w http.ResponseWriter, r *http.Request) (err error) {
var result *s3.GetObjectOutput

if r.Header.Get("Range") != "" {
result, err = b.svc.GetObject(&s3.GetObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
Range: aws.String(r.Header.Get("Range")),
})

w.WriteHeader(206)
w.Header().Set("Content-Range", *result.ContentRange)
w.Header().Set("Content-Length", strconv.FormatInt(*result.ContentLength, 10))
w.Header().Set("Accept-Ranges", "bytes")

} else {
result, err = b.svc.GetObject(&s3.GetObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
})

}

if err != nil {
if aerr, ok := err.(awserr.Error); ok {
if aerr.Code() == s3.ErrCodeNoSuchKey || aerr.Code() == "NotFound" {
err = backends.NotFoundErr
}
}
return
}

_, err = io.Copy(w, result.Body)

return
}

func mapMetadata(m backends.Metadata) map[string]*string {
return map[string]*string{
"Expiry": aws.String(strconv.FormatInt(m.Expiry.Unix(), 10)),
Expand Down
2 changes: 2 additions & 0 deletions backends/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package backends
import (
"errors"
"io"
"net/http"
"time"
)

Expand All @@ -13,6 +14,7 @@ type StorageBackend interface {
Get(key string) (Metadata, io.ReadCloser, error)
Put(key string, r io.Reader, expiry time.Time, deleteKey, accessKey string) (Metadata, error)
PutMetadata(key string, m Metadata) error
ServeFile(key string, w http.ResponseWriter, r *http.Request) error
Size(key string) (int64, error)
}

Expand Down
11 changes: 3 additions & 8 deletions fileserve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"io"
"net/http"
"net/url"
"strconv"
Expand Down Expand Up @@ -61,15 +60,11 @@ func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
}

if r.Method != "HEAD" {
_, reader, err := storageBackend.Get(fileName)
if err != nil {
oopsHandler(c, w, r, RespAUTO, "Unable to open file.")
return
}
defer reader.Close()

if _, err = io.CopyN(w, reader, metadata.Size); err != nil {
storageBackend.ServeFile(fileName, w, r)
if err != nil {
oopsHandler(c, w, r, RespAUTO, err.Error())
return
}
}
}
Expand Down

0 comments on commit 9f7e6b6

Please sign in to comment.