@cryptotaxi247 / kubo / commits / 43c61a4e4

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 +}