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 serve
grunt build grunt build
sh transfer-server/run.sh go run transfersh-server/*.go -provider=local --port 8080 --temp=/tmp/ --basedir=/tmp/
``` ```
## Build ## Build

View File

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

View File

@ -51,6 +51,8 @@ var config struct {
Temp string Temp string
} }
var storage Storage
func init() { func init() {
config.AWS_ACCESS_KEY = os.Getenv("AWS_ACCESS_KEY") config.AWS_ACCESS_KEY = os.Getenv("AWS_ACCESS_KEY")
config.AWS_SECRET_KEY = os.Getenv("AWS_SECRET_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") port := flag.String("port", "8080", "port number, default: 8080")
temp := flag.String("temp", "", "") temp := flag.String("temp", "", "")
basedir := flag.String("basedir", "", "")
logpath := flag.String("log", "", "") logpath := flag.String("log", "", "")
provider := flag.String("provider", "s3", "")
flag.Parse() flag.Parse()
@ -127,6 +131,24 @@ func main() {
} }
config.Temp = *temp 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("Transfer.sh server started. :%v using temp folder: %s", *port, config.Temp)
log.Printf("---------------------------") 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
}