1
0
mirror of https://github.com/dutchcoders/transfer.sh.git synced 2020-11-18 19:53:40 -08:00

Merge branch 'master' of https://github.com/dutchcoders/transfer.sh into uvis-dev

This commit is contained in:
Uvis Grinfelds 2014-10-20 16:28:27 +02:00
commit d5645ef501
5 changed files with 160 additions and 85 deletions

View File

@ -51,7 +51,7 @@ go get github.com/kennygrant/sanitize
grunt serve
grunt build
sh transfer-server/run.sh
go run transfersh-server/*.go -provider=local --port 8080 --temp=/tmp/ --basedir=/tmp/
```
## Build

View File

@ -35,19 +35,18 @@ import (
"errors"
"fmt"
"github.com/dutchcoders/go-clamd"
"github.com/goamz/goamz/s3"
"github.com/golang/gddo/httputil/header"
"github.com/gorilla/mux"
"github.com/kennygrant/sanitize"
"io"
"io/ioutil"
"strconv"
"log"
"math/rand"
"mime"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
html_template "html/template"
@ -112,13 +111,6 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
return
}
bucket, err := getBucket()
if err != nil {
log.Println(err)
http.Error(w, "Error occured copying to output stream", 500)
return
}
token := Encode(10000000 + int64(rand.Intn(1000000000)))
w.Header().Set("Content-Type", "text/plain")
@ -175,18 +167,16 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
contentLength := n
key := fmt.Sprintf("%s/%s", token, filename)
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
log.Printf("Uploading %s %d %s", key, contentLength, contentType)
if err = bucket.PutReader(key, reader, contentLength, contentType, s3.PublicRead, s3.Options{}); err != nil {
if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
log.Print(err)
http.Error(w, err.Error(), 500)
return
}
fmt.Fprintf(w, "https://transfer.sh/%s\n", key)
fmt.Fprintf(w, "https://transfer.sh/%s/%s\n", token, filename)
}
}
}
@ -285,22 +275,13 @@ func putHandler(w http.ResponseWriter, r *http.Request) {
contentType = mime.TypeByExtension(filepath.Ext(vars["filename"]))
}
key := fmt.Sprintf("%s/%s", Encode(10000000+int64(rand.Intn(1000000000))), filename)
token := Encode(10000000+int64(rand.Intn(1000000000)))
log.Printf("Uploading %s %d %s", key, contentLength, contentType)
log.Printf("Uploading %s %d %s", token, filename, contentLength, contentType)
var b *s3.Bucket
var err error
b, err = getBucket()
if err != nil {
http.Error(w, errors.New("Could not open bucket").Error(), 500)
return
}
err = b.PutReader(key, reader, contentLength, contentType, s3.PublicRead, s3.Options{})
if err != nil {
if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
http.Error(w, errors.New("Could not save file").Error(), 500)
return
}
@ -309,7 +290,7 @@ func putHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "https://transfer.sh/%s\n", key)
fmt.Fprintf(w, "https://transfer.sh/%s/%s\n", token, filename)
}
func zipHandler(w http.ResponseWriter, r *http.Request) {
@ -317,22 +298,19 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
files := vars["files"]
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
filename := fmt.Sprintf("transfersh-%d.zip", uint16(time.Now().UnixNano()))
zipfilename := fmt.Sprintf("transfersh-%d.zip", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", zipfilename))
w.Header().Set("Connection", "close")
zw := zip.NewWriter(w)
for _, key := range strings.Split(files, ",") {
rc, err := b.GetResponse(key)
token := sanitize.Path(strings.Split(key, "/")[0])
filename := sanitize.Path(strings.Split(key, "/")[1])
reader, _, _, err := storage.Get(token, filename)
if err != nil {
if err.Error() == "The specified key does not exist." {
http.Error(w, "File not found", 404)
@ -344,7 +322,7 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
}
}
defer rc.Body.Close()
defer reader.Close()
header := &zip.FileHeader{
Name: strings.Split(key, "/")[1],
@ -353,8 +331,6 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
ModifiedDate: uint16(time.Now().UnixNano()),
}
fi := rc.Body
fw, err := zw.CreateHeader(header)
if err != nil {
@ -363,7 +339,7 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
return
}
if _, err = io.Copy(fw, fi); err != nil {
if _, err = io.Copy(fw, reader); err != nil {
log.Printf("%s", err.Error())
http.Error(w, "Internal server error.", 500)
return
@ -382,16 +358,10 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
files := vars["files"]
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
filename := fmt.Sprintf("transfersh-%d.tar.gz", uint16(time.Now().UnixNano()))
tarfilename := fmt.Sprintf("transfersh-%d.tar.gz", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/x-gzip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", tarfilename))
w.Header().Set("Connection", "close")
os := gzip.NewWriter(w)
@ -401,7 +371,10 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
defer zw.Close()
for _, key := range strings.Split(files, ",") {
rc, err := b.GetResponse(key)
token := strings.Split(key, "/")[0]
filename := strings.Split(key, "/")[1]
reader, _, contentLength, err := storage.Get(token, filename)
if err != nil {
if err.Error() == "The specified key does not exist." {
http.Error(w, "File not found", 404)
@ -413,9 +386,7 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
}
}
defer rc.Body.Close()
contentLength, err := strconv.Atoi(rc.Header.Get("Content-Length"))
defer reader.Close()
header := &tar.Header{
Name: strings.Split(key, "/")[1],
@ -429,9 +400,7 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
return
}
fi := rc.Body
if _, err = io.Copy(zw, fi); err != nil {
if _, err = io.Copy(zw, reader); err != nil {
log.Printf("%s", err.Error())
http.Error(w, "Internal server error.", 500)
return
@ -444,23 +413,20 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
files := vars["files"]
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
filename := fmt.Sprintf("transfersh-%d.tar", uint16(time.Now().UnixNano()))
tarfilename := fmt.Sprintf("transfersh-%d.tar", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/x-tar")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", tarfilename))
w.Header().Set("Connection", "close")
zw := tar.NewWriter(w)
defer zw.Close()
for _, key := range strings.Split(files, ",") {
rc, err := b.GetResponse(key)
token := strings.Split(key, "/")[0]
filename := strings.Split(key, "/")[1]
reader, _, contentLength, err := storage.Get(token, filename)
if err != nil {
if err.Error() == "The specified key does not exist." {
http.Error(w, "File not found", 404)
@ -472,9 +438,7 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
}
}
defer rc.Body.Close()
contentLength, err := strconv.Atoi(rc.Header.Get("Content-Length"))
defer reader.Close()
header := &tar.Header{
Name: strings.Split(key, "/")[1],
@ -488,9 +452,7 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
return
}
fi := rc.Body
if _, err = io.Copy(zw, fi); err != nil {
if _, err = io.Copy(zw, reader); err != nil {
log.Printf("%s", err.Error())
http.Error(w, "Internal server error.", 500)
return
@ -504,15 +466,7 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
token := vars["token"]
filename := vars["filename"]
key := fmt.Sprintf("%s/%s", token, filename)
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
rc, err := b.GetResponse(key)
reader, contentType, contentLength, err := storage.Get(token, filename)
if err != nil {
if err.Error() == "The specified key does not exist." {
http.Error(w, "File not found", 404)
@ -524,15 +478,13 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
}
}
defer rc.Body.Close()
defer reader.Close()
contentType := rc.Header.Get("Content-Type")
w.Header().Set("Content-Type", contentType)
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
mediaType, _, _ := mime.ParseMediaType(contentType)
fmt.Println(mediaType)
switch {
case mediaType == "text/html":
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
@ -546,7 +498,7 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Connection", "close")
if _, err = io.Copy(w, rc.Body); err != nil {
if _, err = io.Copy(w, reader); err != nil {
http.Error(w, "Error occured copying to output stream", 500)
return
}

View File

@ -51,6 +51,8 @@ var config struct {
Temp string
}
var storage Storage
func init() {
config.AWS_ACCESS_KEY = os.Getenv("AWS_ACCESS_KEY")
config.AWS_SECRET_KEY = os.Getenv("AWS_SECRET_KEY")
@ -111,7 +113,9 @@ func main() {
port := flag.String("port", "8080", "port number, default: 8080")
temp := flag.String("temp", "", "")
basedir := flag.String("basedir", "", "")
logpath := flag.String("log", "", "")
provider := flag.String("provider", "s3", "")
flag.Parse()
@ -127,6 +131,24 @@ func main() {
}
config.Temp = *temp
var err error
switch *provider {
case "s3":
storage, err = NewS3Storage()
case "local":
if *basedir == "" {
log.Panic("basedir not set")
}
storage, err = NewLocalStorage(*basedir)
}
if err != nil {
log.Panic("Error while creating storage.")
}
log.Printf("Transfer.sh server started. :%v using temp folder: %s", *port, config.Temp)
log.Printf("---------------------------")

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,100 @@
package main
import (
"io"
"github.com/goamz/goamz/s3"
"strconv"
"fmt"
"os"
"path/filepath"
)
type Storage interface {
Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
}
type LocalStorage struct {
Storage
basedir string
}
func NewLocalStorage(basedir string) (*LocalStorage, error) {
return &LocalStorage {basedir: basedir}, nil
}
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
path := filepath.Join(s.basedir, token, filename)
// content type , content length
if reader, err = os.Open(path); err != nil {
return
}
var fi os.FileInfo
if fi, err = os.Lstat(path); err != nil {
}
contentLength = uint64(fi.Size())
contentType = ""
return
}
func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
var f io.WriteCloser
var err error
path := filepath.Join(s.basedir, token)
if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
return err
}
if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
fmt.Printf("%s", err)
return err
}
defer f.Close()
if _, err = io.Copy(f, reader); err != nil {
return err
}
return nil
}
type S3Storage struct {
Storage
bucket *s3.Bucket
}
func NewS3Storage() (*S3Storage, error) {
bucket, err := getBucket()
if err != nil {
return nil, err
}
return &S3Storage {bucket: bucket}, nil
}
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
key := fmt.Sprintf("%s/%s", token, filename)
// content type , content length
response, err := s.bucket.GetResponse(key)
contentType = ""
contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
reader = response.Body
return
}
func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
key := fmt.Sprintf("%s/%s", token, filename)
err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
return err
}