From 43c61a4e4b6c070ee04d9195eea3eec9f2929059 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Fri, 24 Oct 2014 14:32:39 -0700 Subject: [PATCH] commands/http: Moved HTTP RPC handler into commands/http --- commands/http/handler.go | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 commands/http/handler.go diff --git a/commands/http/handler.go b/commands/http/handler.go new file mode 100644 index 000000000..42497a0a2 --- /dev/null +++ b/commands/http/handler.go @@ -0,0 +1,80 @@ +package http + +import ( + "io" + "net/http" + "strings" + + cmds "github.com/jbenet/go-ipfs/commands" + "github.com/jbenet/go-ipfs/core/commands" +) + +type Handler struct{} + +// TODO: store ipfsnode context + +func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + path := strings.Split(r.URL.Path, "/")[3:] + opts := getOptions(r) + + // TODO: get args + + // ensure the requested command exists, otherwise 404 + _, err := commands.Root.Get(path) + if err != nil { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("404 page not found")) + return + } + + // build the Request and call the command + req := cmds.NewRequest(path, opts, nil, nil) + res := commands.Root.Call(req) + + // set the Content-Type based on res output + if _, ok := res.Value().(io.Reader); ok { + // TODO: set based on actual Content-Type of file + w.Header().Set("Content-Type", "application/octet-stream") + } else { + // TODO: get proper MIME type for encoding from multicodec lib + enc, _ := req.Option(cmds.EncShort) + w.Header().Set("Content-Type", "application/"+enc.(string)) + } + + // if response contains an error, write an HTTP error status code + if e := res.Error(); e != nil { + if e.Code == cmds.ErrClient { + w.WriteHeader(http.StatusBadRequest) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + } + + _, err = io.Copy(w, res) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(err.Error())) + } +} + +// getOptions returns the command options in the given HTTP request +// (from the querystring and request body) +func getOptions(r *http.Request) map[string]interface{} { + opts := make(map[string]interface{}) + + query := r.URL.Query() + for k, v := range query { + opts[k] = v[0] + } + + // TODO: get more options from request body (formdata, json, etc) + + _, short := opts[cmds.EncShort] + _, long := opts[cmds.EncLong] + if !short && !long { + opts[cmds.EncShort] = cmds.JSON + } + + return opts +}