commands/http: Moved HTTP RPC handler into commands/http
Matt Bell committed
Oct 24, 2014 at 14:32 UTC
43c61a4e4b6c070ee04d9195eea3eec9f2929059
1 file changed
+80
commands/http/handler.go
new
+80
@@ -0,0 +1,80 @@
1
+package http
2
+
3
+import (
4
+ "io"
5
+ "net/http"
6
+ "strings"
7
+
8
+ cmds "github.com/jbenet/go-ipfs/commands"
9
+ "github.com/jbenet/go-ipfs/core/commands"
10
+)
11
+
12
+type Handler struct{}
13
+
14
+// TODO: store ipfsnode context
15
+
16
+func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
17
+ path := strings.Split(r.URL.Path, "/")[3:]
18
+ opts := getOptions(r)
19
+
20
+ // TODO: get args
21
+
22
+ // ensure the requested command exists, otherwise 404
23
+ _, err := commands.Root.Get(path)
24
+ if err != nil {
25
+ w.WriteHeader(http.StatusNotFound)
26
+ w.Write([]byte("404 page not found"))
27
+ return
28
+ }
29
+
30
+ // build the Request and call the command
31
+ req := cmds.NewRequest(path, opts, nil, nil)
32
+ res := commands.Root.Call(req)
33
+
34
+ // set the Content-Type based on res output
35
+ if _, ok := res.Value().(io.Reader); ok {
36
+ // TODO: set based on actual Content-Type of file
37
+ w.Header().Set("Content-Type", "application/octet-stream")
38
+ } else {
39
+ // TODO: get proper MIME type for encoding from multicodec lib
40
+ enc, _ := req.Option(cmds.EncShort)
41
+ w.Header().Set("Content-Type", "application/"+enc.(string))
42
+ }
43
+
44
+ // if response contains an error, write an HTTP error status code
45
+ if e := res.Error(); e != nil {
46
+ if e.Code == cmds.ErrClient {
47
+ w.WriteHeader(http.StatusBadRequest)
48
+ } else {
49
+ w.WriteHeader(http.StatusInternalServerError)
50
+ }
51
+ }
52
+
53
+ _, err = io.Copy(w, res)
54
+ if err != nil {
55
+ w.WriteHeader(http.StatusInternalServerError)
56
+ w.Header().Set("Content-Type", "text/plain")
57
+ w.Write([]byte(err.Error()))
58
+ }
59
+}
60
+
61
+// getOptions returns the command options in the given HTTP request
62
+// (from the querystring and request body)
63
+func getOptions(r *http.Request) map[string]interface{} {
64
+ opts := make(map[string]interface{})
65
+
66
+ query := r.URL.Query()
67
+ for k, v := range query {
68
+ opts[k] = v[0]
69
+ }
70
+
71
+ // TODO: get more options from request body (formdata, json, etc)
72
+
73
+ _, short := opts[cmds.EncShort]
74
+ _, long := opts[cmds.EncLong]
75
+ if !short && !long {
76
+ opts[cmds.EncShort] = cmds.JSON
77
+ }
78
+
79
+ return opts
80
+}