Torrent: Ranged requests so torrents work

This commit is contained in:
Andrei Marcu 2020-03-18 17:26:43 -07:00
parent 3167ab7ff0
commit 9f7e6b6eea
4 changed files with 56 additions and 8 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"path" "path"
"time" "time"
@ -82,6 +83,18 @@ func (b LocalfsBackend) Get(key string) (metadata backends.Metadata, f io.ReadCl
return 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 { func (b LocalfsBackend) writeMetadata(key string, metadata backends.Metadata) error {
metaPath := path.Join(b.metaPath, key) metaPath := path.Join(b.metaPath, key)

View File

@ -3,6 +3,7 @@ package s3
import ( import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"strconv" "strconv"
"time" "time"
@ -79,6 +80,43 @@ func (b S3Backend) Get(key string) (metadata backends.Metadata, r io.ReadCloser,
return 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 { func mapMetadata(m backends.Metadata) map[string]*string {
return map[string]*string{ return map[string]*string{
"Expiry": aws.String(strconv.FormatInt(m.Expiry.Unix(), 10)), "Expiry": aws.String(strconv.FormatInt(m.Expiry.Unix(), 10)),

View File

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

View File

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
@ -61,15 +60,11 @@ func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
} }
if r.Method != "HEAD" { 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()) oopsHandler(c, w, r, RespAUTO, err.Error())
return
} }
} }
} }