package localfs import ( "errors" "io" "io/ioutil" "net/http" "os" "path" "github.com/andreimarcu/linx-server/backends" "github.com/andreimarcu/linx-server/torrent" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/zeebo/bencode" ) type S3Backend struct { bucket string svc *S3 } func (b S3Backend) Delete(key string) error { input := &s3.DeleteObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } _, err := b.svc.DeleteObject(input) return os.Remove(path.Join(b.bucket, key)) } func (b S3Backend) Exists(key string) (bool, error) { input := &s3.HeadObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } _, err := b.svc.HeadObject(input) return err == nil, err } func (b S3Backend) Get(key string) ([]byte, error) { input := &s3.GetObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } result, err := b.svc.GetObject(input) if err != nil { return []byte{}, err } defer result.Body.Close() return ioutil.ReadAll(result.Body) } func (b S3Backend) Put(key string, r io.Reader) (int64, error) { uploader := s3manager.NewUploaderWithClient(b.svc) input := &s3manager.UploadInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), Body: r, } result, err := uploader.Upload(input) if err != nil { return 0, err } return -1, nil } func (b S3Backend) Open(key string) (backends.ReadSeekCloser, error) { input := &s3.GetObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } result, err := b.svc.GetObject(input) if err != nil { return nil, err } return result.Body, nil } func (b S3Backend) ServeFile(key string, w http.ResponseWriter, r *http.Request) { input := &s3.GetObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } result, err := b.svc.GetObject(input) if err != nil { return err } defer result.Body.Close() http.ServeContent(w, r, key, *result.LastModified, result.Body) return nil } func (b S3Backend) Size(key string) (int64, error) { input := &s3.HeadObjectInput{ Bucket: aws.String(b.bucket), Key: aws.String(key), } result, err := b.svc.HeadObject(input) if err != nil { return 0, err } return *result.ContentLength, nil } func (b S3Backend) GetTorrent(fileName string, url string) (t torrent.Torrent, err error) { input := &s3.GetObjectTorrentInput{ Bucket: aws.String(b.bucket), Key: aws.String(fileName), } result, err := b.svc.GetObjectTorrent(input) if err != nil { return } defer result.Body.Close() data, err := ioutil.ReadAll(result.Body) if err != nil { return } err = bencode.DecodeBytes(data, &t) if err != nil { return } t.Info.Name = fileName t.UrlList = []string{url} return } func (b S3Backend) List() ([]string, error) { var output []string input := &s3.ListObjectsInput{ bucket: aws.String(b.bucket), } results, err := b.svc.ListObjects(input) if err != nil { return nil, err } for _, object := range results.Contents { output = append(output, *object.Key) } return output, nil } func NewS3Backend(bucket string, region string, endpoint string) S3Backend { awsConfig := &aws.Config{} if region != "" { awsConfig.Region = aws.String(region) } if endpoint != "" { awsConfig.Endpoint = aws.String(endpoint) } sess := session.Must(session.NewSession(awsConfig)) svc := s3.New(sess) return S3Backend{bucket: bucket, svc: svc} }