@cryptotaxi247 / kubo / commits / 40858b43e

commands/http: Added stream argument handling to client and request parser

Matt Bell committed Nov 2, 2014 at 17:58 UTC 40858b43edc65539fb4c27991b408260e090ef51
2 files changed +45 -17
commands/http/client.go
+22 -6
@@ -6,6 +6,7 @@ import (
6 "fmt"
7 "io"
8 "net/http"
9 + "os"
10 "strings"
11
12 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
@@ -14,7 +15,7 @@ import (
15 cmds "github.com/jbenet/go-ipfs/commands"
16 )
17
17 -const ApiPath = "/api/v0"
18 +const ApiPath = "/api/v0" // TODO: make configurable
19
20 func Send(req cmds.Request) (cmds.Response, error) {
21 addr, err := ma.NewMultiaddr(req.Context().Config.Addresses.API)
@@ -40,18 +41,33 @@ func Send(req cmds.Request) (cmds.Response, error) {
41 req.SetOption(cmds.EncLong, cmds.JSON)
42 }
43
44 + // TODO: handle multiple files with multipart
45 + var in io.Reader
46 +
47 query := "?"
48 for k, v := range req.Options() {
49 query += "&" + k + "=" + v.(string)
50 }
47 - for _, arg := range req.Arguments() {
48 - s, ok := arg.(string)
49 - if ok {
50 - query += "&arg=" + s
51 +
52 + args := req.Arguments()
53 + for i, arg := range args {
54 + if req.Command().Arguments[i].Type == cmds.ArgString {
55 + query += "&arg=" + arg.(string)
56 +
57 + } else {
58 + // TODO: multipart
59 + if in != nil {
60 + return nil, fmt.Errorf("Currently, only one file stream is possible per request")
61 + }
62 + in, err = os.Open(arg.(string))
63 + if err != nil {
64 + return nil, err
65 + }
66 + args[i] = in
67 }
68 }
69
54 - httpRes, err := http.Post(url+query, "application/octet-stream", nil)
70 + httpRes, err := http.Post(url+query, "application/octet-stream", in)
71 if err != nil {
72 return nil, err
73 }
commands/http/parse.go
+23 -11
@@ -10,7 +10,7 @@ import (
10 // Parse parses the data in a http.Request and returns a command Request object
11 func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
12 path := strings.Split(r.URL.Path, "/")[3:]
13 - args := make([]interface{}, 0)
13 + stringArgs := make([]string, 0)
14
15 cmd, err := root.Get(path[:len(path)-1])
16 if err != nil {
@@ -24,36 +24,48 @@ func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
24
25 // if the last string in the path isn't a subcommand, use it as an argument
26 // e.g. /objects/Qabc12345 (we are passing "Qabc12345" to the "objects" command)
27 - args = append(args, path[len(path)-1])
27 + stringArgs = append(stringArgs, path[len(path)-1])
28 path = path[:len(path)-1]
29
30 } else {
31 cmd = sub
32 }
33
34 - opts, args2 := parseOptions(r)
35 - args = append(args, args2...)
34 + opts, stringArgs2 := parseOptions(r)
35 + stringArgs = append(stringArgs, stringArgs2...)
36 +
37 + // Note that the argument handling here is dumb, it does not do any error-checking.
38 + // (Arguments are further processed when the request is passed to the command to run)
39 + args := make([]interface{}, len(cmd.Arguments))
40 + for i, arg := range cmd.Arguments {
41 + if arg.Type == cmds.ArgString {
42 + if len(stringArgs) > 0 {
43 + args[i] = stringArgs[0]
44 + stringArgs = stringArgs[1:]
45 + }
46 +
47 + } else {
48 + // TODO: create multipart streams for file args
49 + args[i] = r.Body
50 + }
51 + }
52
53 return cmds.NewRequest(path, opts, args, cmd), nil
54 }
55
40 -func parseOptions(r *http.Request) (map[string]interface{}, []interface{}) {
56 +func parseOptions(r *http.Request) (map[string]interface{}, []string) {
57 opts := make(map[string]interface{})
42 - args := make([]interface{}, 0)
58 + var args []string
59
60 query := r.URL.Query()
61 for k, v := range query {
62 if k == "arg" {
47 - for _, s := range v {
48 - args = append(args, interface{}(s))
49 - }
63 + args = v
64 } else {
65 opts[k] = v[0]
66 }
67 }
68
55 - // TODO: create multipart streams for file args
56 -
69 // default to setting encoding to JSON
70 _, short := opts[cmds.EncShort]
71 _, long := opts[cmds.EncLong]