-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
114 lines (95 loc) · 2.45 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"context"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/caarlos0/httperr"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"gocloud.dev/blob"
_ "gocloud.dev/blob/azureblob"
_ "gocloud.dev/blob/gcsblob"
_ "gocloud.dev/blob/s3blob"
)
var (
auths stringSlice
bucket string
listen string
)
func main() {
flag.Var(&auths, "authorize", "user/passwords that can authenticate in the user:pwd format (e.g.: carlos:asd123)")
flag.StringVar(&bucket, "bucket", "", "bucket name (e.g.: s3://foo)")
flag.StringVar(&listen, "listen", "127.0.0.1:8080", "address to listen to (e.g. 127.0.0.1:9090)")
flag.Parse()
ctx := context.Background()
bucket, err := blob.OpenBucket(ctx, bucket)
if err != nil {
log.Fatalln(err)
}
defer bucket.Close()
var r = chi.NewRouter()
r.Use(middleware.Logger, middleware.Recoverer)
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "ok")
})
r.Get("/{asset}", httperr.NewF(func(w http.ResponseWriter, r *http.Request) error {
var path = chi.URLParam(r, "asset")
user, pwd, ok := r.BasicAuth()
if !(ok && isAuthorized(user+":"+pwd)) {
log.Println("unauthorized:", user)
return httperr.Wrap(fmt.Errorf("missing/invalid authorization"), http.StatusUnauthorized)
}
reader, err := bucket.NewReader(ctx, path, nil)
if err != nil {
return httperr.Wrap(err, http.StatusNotFound)
}
defer reader.Close()
if _, err := io.Copy(w, reader); err != nil {
return httperr.Wrap(err, http.StatusInternalServerError)
}
return nil
}).ServeHTTP)
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
srv := &http.Server{
Addr: listen,
Handler: r,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
log.Println("listening on", listen)
<-done
log.Println("stopping")
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("couldn't stop server: %+v", err)
}
}
type stringSlice []string
func (i *stringSlice) String() string {
return "[" + strings.Join(*i, ", ") + "]"
}
func (i *stringSlice) Set(value string) error {
*i = append(*i, value)
return nil
}
func isAuthorized(input string) bool {
for _, auth := range auths {
if input == auth {
return true
}
}
return false
}