-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.go
115 lines (97 loc) · 2.8 KB
/
server.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
115
package httpfs
// server-side httpfs code
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
)
// file action gets its own type to avoid mixing up with other strings
type action string
// httpfs actions, handled at /actionName/ (e.g. /ls/, /mkdir/, ...)
const (
APPEND action = "append"
LS action = "ls"
MKDIR action = "mkdir"
PUT action = "put"
READ action = "read"
RM action = "rm"
TOUCH action = "touch"
)
// RegisterHandlers sets up the http handlers needed for the httpfs protocol (calling go's http.Handle).
// After RegisterHandlers, http.ListenAndServe may be called.
func RegisterHandlers() {
m := map[action]handlerFunc{
APPEND: handleAppend,
LS: handleLs,
MKDIR: handleMkdir,
PUT: handlePut,
READ: handleRead,
RM: handleRemove,
TOUCH: handleTouch,
}
for k, v := range m {
http.HandleFunc("/"+string(k)+"/", newHandler(k, v))
}
http.Handle("/fs/", http.StripPrefix("/fs/", http.FileServer(http.Dir("."))))
}
// general handler func for file name, optional URL query, input data and response writer.
type handlerFunc func(fname string, data []byte, w io.Writer, query url.Values) error
func newHandler(prefix action, f handlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fname := r.URL.Path[len(prefix)+2:] // strip "/prefix/"
query := r.URL.Query()
data, err := ioutil.ReadAll(r.Body)
Log("httpfs req:", prefix, fname, query.Encode(), len(data), "B payload")
if err != nil {
Log("httpfs err:", prefix, fname, ":", err)
http.Error(w, err.Error(), http.StatusBadRequest)
}
err2 := f(fname, data, w, query)
if err2 != nil {
Log("httpfs err:", prefix, fname, ":", err2)
http.Error(w, err2.Error(), http.StatusInternalServerError)
}
}
}
func handleAppend(fname string, data []byte, w io.Writer, q url.Values) error {
size := int64(-1)
s := q.Get("size")
if s != "" {
var err error
size, err = strconv.ParseInt(s, 0, 64)
if err != nil {
return err
}
}
return localAppend(fname, data, size)
}
func handlePut(fname string, data []byte, w io.Writer, q url.Values) error {
return localPut(fname, data)
}
func handleLs(fname string, data []byte, w io.Writer, q url.Values) error {
ls, err := localLs(fname)
if err != nil {
return err
}
return json.NewEncoder(w).Encode(ls)
}
func handleMkdir(fname string, data []byte, w io.Writer, q url.Values) error {
return localMkdir(fname)
}
func handleTouch(fname string, data []byte, w io.Writer, q url.Values) error {
return localTouch(fname)
}
func handleRead(fname string, data []byte, w io.Writer, q url.Values) error {
b, err := localRead(fname)
if err != nil {
return err
}
_, err2 := w.Write(b)
return err2
}
func handleRemove(fname string, data []byte, w io.Writer, q url.Values) error {
return localRemove(fname)
}