-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage.go
143 lines (116 loc) · 3 KB
/
storage.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Storage-Go provides an implementation of the storage protocol (subset of WebDav)
// Version: 1.0
// Author: Alexander Weigl <[email protected]>
package main
import "path/filepath"
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
)
// The size of the copy buffer from the http to the file system.
const BUFFER_SIZE = 8 * 1024
// Handler of the StorageProtocol
//
// Providing the functionality for access of PUT, GET, POST, DELETE to
// arbitrary path
type StorageHandler struct {
// root directory for storing and retrieve the files
RootDir string
}
// PathSplit splits file path into the dirname and basename
func PathSplit(path string) (string, string) {
return filepath.Dir(path), filepath.Base(path)
}
// ServeGet handles all GET requests
func ServeGet(w http.ResponseWriter, r *http.Request, path string) {
// Copying file into the response
file, err := os.Open(path)
if err == nil {
w.WriteHeader(200)
buffer := make([]byte, BUFFER_SIZE)
for {
count, err := file.Read(buffer)
w.Write(buffer[:count])
if err != nil {
break
}
}
if err != io.EOF {
fmt.Printf("error during reading file: %s \n", err)
}
fmt.Fprintf(w, "ok")
}
}
// ServePut handles all Put requests
func ServePut(w http.ResponseWriter, r *http.Request, path string) {
dir, _ := PathSplit(path)
os.MkdirAll(dir, 0755)
buffer, err := ioutil.ReadAll(r.Body)
if err != nil {
w.WriteHeader(500)
fmt.Fprintf(w, "error %s", err)
return
}
err = ioutil.WriteFile(path, buffer, 0755)
if err != nil {
w.WriteHeader(500)
fmt.Fprintf(w, "error %s", err)
return
}
w.WriteHeader(200)
fmt.Fprintf(w, "ok")
}
// ServePost handles POST requests
func ServePost(w http.ResponseWriter, r *http.Request, path string) {
w.WriteHeader(501)
fmt.Fprintf(w, "not implemented")
}
// ServeDelete handles Delete requests
func ServeDelete(w http.ResponseWriter, r *http.Request, path string) {
err := os.RemoveAll(path)
if err != nil {
w.WriteHeader(500)
fmt.Fprintf(w, "err: %s", err)
}
}
// ServeHTTP Handling the FileStorage Protocol
func (sh *StorageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
uri, _ := filepath.Abs(r.RequestURI)
method := r.Method
path := sh.RootDir + uri
fmt.Printf("Request to: %s as %s\n", uri, method)
fmt.Printf("Routing to: %s", path)
switch method {
case "GET":
ServeGet(w, r, path)
case "PUT":
ServePut(w, r, path)
case "DELETE":
ServeDelete(w, r, path)
case "POST":
ServePost(w, r, path)
}
}
// GetOption retrieves an option from the environment,
// if no such value exists, fallback is return
func GetOption(key, fallback string) string {
value := os.Getenv(key)
if value == "" {
return fallback
}
return value
}
func main() {
bind_host := GetOption("STORAGE_HOST", ":8080")
fmt.Printf("Starting server, listening on %s\n", bind_host)
// http.HandleFunc("/", handler)
handler := new(StorageHandler)
handler.RootDir = GetOption("STORAGE_ROOT", "./test")
err := http.ListenAndServe(":8080", handler)
if err != nil {
fmt.Println(err)
}
}