Skip to content

Instantly share code, notes, and snippets.

@rochacon
Last active September 28, 2018 12:20
Show Gist options
  • Save rochacon/0eafcd565e6f5ac05e00 to your computer and use it in GitHub Desktop.
Save rochacon/0eafcd565e6f5ac05e00 to your computer and use it in GitHub Desktop.
S3 Proxy in Go
package main
import (
"crypto/sha256"
"flag"
"fmt"
"github.com/gorilla/mux"
"hash"
"io"
"launchpad.net/goamz/aws"
"launchpad.net/goamz/s3"
"log"
"net/http"
)
var BucketName string
func main() {
flag.StringVar(&BucketName, "bucket", "", "The name of the bucket to be used")
flag.Parse()
if BucketName == "" {
log.Fatalf("Specify a bucket name")
}
r := mux.NewRouter()
r.HandleFunc("/{path:.+}", download).Methods("GET")
r.HandleFunc("/{path:.+}", upload).Methods("PUT")
http.Handle("/", r)
log.Println("Listening on :8000")
log.Println("Bucket:", BucketName)
log.Fatal(http.ListenAndServe(":8000", nil))
}
func getBucket() (*s3.Bucket, error) {
auth, err := aws.EnvAuth()
if err != nil {
return nil, err
}
s3conn := s3.New(auth, aws.Region{S3Endpoint: "https://s3.amazonaws.com"})
bucket := s3conn.Bucket(BucketName)
return bucket, nil
}
func download(w http.ResponseWriter, r *http.Request) {
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
reader, err := b.GetReader(r.URL.Path)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer reader.Close()
buf := make([]byte, 8192)
for {
n, err := reader.Read(buf)
if n > 0 {
w.Write(buf[:n])
}
if n == 0 {
break
}
if err != nil {
http.Error(w, err.Error(), 500)
return
}
}
}
func upload(w http.ResponseWriter, r *http.Request) {
b, err := getBucket()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
bodyReader := &ReadHasher{h: sha256.New(), r: r.Body}
err = b.PutReader(r.URL.Path, bodyReader, r.ContentLength, "", "private")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
fmt.Fprintf(w, "%x", bodyReader.Sum(nil))
}
type ReadHasher struct {
h hash.Hash
r io.Reader
}
func (rh *ReadHasher) Read(buf []byte) (n int, err error) {
n, err = rh.r.Read(buf)
if err != nil {
return n, err
}
rh.h.Write(buf[:n])
return
}
func (rh *ReadHasher) Sum(b []byte) []byte {
return rh.h.Sum(b)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment