updated readme & go formatted code

This commit is contained in:
Remco 2014-10-20 14:54:42 +02:00
parent 16ad1833d2
commit b8eaf23805
4 changed files with 92 additions and 91 deletions

View file

@ -1,6 +1,8 @@
# transfer.sh # transfer.sh
Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance. Transfer.sh currently runs on top of Amazon S3. Other storage types will be added shortly. Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance.
Transfer.sh support currently the s3 (Amazon S3) provider and local file system (local).
[![Build Status](https://travis-ci.org/dutchcoders/transfer.sh.svg?branch=master)](https://travis-ci.org/dutchcoders/transfer.sh) [![Build Status](https://travis-ci.org/dutchcoders/transfer.sh.svg?branch=master)](https://travis-ci.org/dutchcoders/transfer.sh)

View file

@ -38,19 +38,19 @@ import (
"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"
html_template "html/template"
"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"
html_template "html/template"
text_template "text/template" text_template "text/template"
"time"
) )
func healthHandler(w http.ResponseWriter, r *http.Request) { func healthHandler(w http.ResponseWriter, r *http.Request) {
@ -101,7 +101,7 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
} }
func notFoundHandler(w http.ResponseWriter, r *http.Request) { func notFoundHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(404), 404) http.Error(w, http.StatusText(404), 404)
} }
func postHandler(w http.ResponseWriter, r *http.Request) { func postHandler(w http.ResponseWriter, r *http.Request) {
@ -169,7 +169,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType) log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil { if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
log.Print(err) log.Print(err)
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), 500)
return return
@ -275,7 +275,7 @@ func putHandler(w http.ResponseWriter, r *http.Request) {
contentType = mime.TypeByExtension(filepath.Ext(vars["filename"])) contentType = mime.TypeByExtension(filepath.Ext(vars["filename"]))
} }
token := Encode(10000000+int64(rand.Intn(1000000000))) token := Encode(10000000 + int64(rand.Intn(1000000000)))
log.Printf("Uploading %s %d %s", token, filename, contentLength, contentType) log.Printf("Uploading %s %d %s", token, filename, contentLength, contentType)
@ -307,8 +307,8 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
zw := zip.NewWriter(w) zw := zip.NewWriter(w)
for _, key := range strings.Split(files, ",") { for _, key := range strings.Split(files, ",") {
token := sanitize.Path(strings.Split(key, "/")[0]) token := sanitize.Path(strings.Split(key, "/")[0])
filename := sanitize.Path(strings.Split(key, "/")[1]) filename := sanitize.Path(strings.Split(key, "/")[1])
reader, _, _, err := storage.Get(token, filename) reader, _, _, err := storage.Get(token, filename)
if err != nil { if err != nil {
@ -322,7 +322,7 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
defer reader.Close() defer reader.Close()
header := &zip.FileHeader{ header := &zip.FileHeader{
Name: strings.Split(key, "/")[1], Name: strings.Split(key, "/")[1],
@ -371,8 +371,8 @@ 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, ",") {
token := strings.Split(key, "/")[0] token := strings.Split(key, "/")[0]
filename := strings.Split(key, "/")[1] filename := strings.Split(key, "/")[1]
reader, _, contentLength, err := storage.Get(token, filename) reader, _, contentLength, err := storage.Get(token, filename)
if err != nil { if err != nil {
@ -386,7 +386,7 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
defer reader.Close() defer reader.Close()
header := &tar.Header{ header := &tar.Header{
Name: strings.Split(key, "/")[1], Name: strings.Split(key, "/")[1],
@ -423,8 +423,8 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
defer zw.Close() defer zw.Close()
for _, key := range strings.Split(files, ",") { for _, key := range strings.Split(files, ",") {
token := strings.Split(key, "/")[0] token := strings.Split(key, "/")[0]
filename := strings.Split(key, "/")[1] filename := strings.Split(key, "/")[1]
reader, _, contentLength, err := storage.Get(token, filename) reader, _, contentLength, err := storage.Get(token, filename)
if err != nil { if err != nil {
@ -438,7 +438,7 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
defer reader.Close() defer reader.Close()
header := &tar.Header{ header := &tar.Header{
Name: strings.Split(key, "/")[1], Name: strings.Split(key, "/")[1],
@ -466,7 +466,7 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
token := vars["token"] token := vars["token"]
filename := vars["filename"] filename := vars["filename"]
reader, contentType, contentLength, err := storage.Get(token, filename) reader, contentType, 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)
@ -478,10 +478,10 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
defer reader.Close() defer reader.Close()
w.Header().Set("Content-Type", contentType) w.Header().Set("Content-Type", contentType)
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10)) w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
mediaType, _, _ := mime.ParseMediaType(contentType) mediaType, _, _ := mime.ParseMediaType(contentType)

View file

@ -131,23 +131,23 @@ func main() {
} }
config.Temp = *temp config.Temp = *temp
var err error
switch *provider { var err error
case "s3":
storage, err = NewS3Storage()
case "local":
if *basedir == "" {
log.Panic("basedir not set")
}
storage, err = NewLocalStorage(*basedir) switch *provider {
} case "s3":
storage, err = NewS3Storage()
case "local":
if *basedir == "" {
log.Panic("basedir not set")
}
if err != nil { storage, err = NewLocalStorage(*basedir)
log.Panic("Error while creating storage.") }
}
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

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