ipfs.go 2.61 KB
Newer Older
Brian Tiger Chow's avatar
Brian Tiger Chow committed
1 2 3
package main

import (
4
	"encoding/json"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
5
	"fmt"
6
	"io"
7
	"net/http"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
8 9
	"os"
	"runtime/pprof"
10
	"strings"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
11

12 13 14
	cmds "github.com/jbenet/go-ipfs/commands"
	"github.com/jbenet/go-ipfs/commands/cli"
	"github.com/jbenet/go-ipfs/core/commands"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
15 16 17 18 19 20
	u "github.com/jbenet/go-ipfs/util"
)

// log is the command logger
var log = u.Logger("cmd/ipfs")

21
const API_PATH = "/api/v0"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
22 23

func main() {
24
	req, err := cli.Parse(os.Args[1:], commands.Root)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
25
	if err != nil {
26
		fmt.Println(err)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
27 28 29
		os.Exit(1)
	}

30 31
	// TODO: call command locally if option tells us to, or if command is CLI-only (e.g. ipfs init)

32
	cmd, err := commands.Root.Get(req.Path())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
33
	if err != nil {
34 35
		fmt.Println(err)
		os.Exit(1)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
36 37
	}

38 39 40 41 42
	res, err := sendRequest(req)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
43

44 45
	if debug, ok := req.Option("debug"); ok && debug.(bool) {
		u.Debug = true
Brian Tiger Chow's avatar
Brian Tiger Chow committed
46

47 48 49 50 51 52 53 54 55 56 57
		// if debugging, setup profiling.
		if u.Debug {
			ofi, err := os.Create("cpu.prof")
			if err != nil {
				fmt.Println(err)
				return
			}
			pprof.StartCPUProfile(ofi)
			defer ofi.Close()
			defer pprof.StopCPUProfile()
		}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
58 59
	}

60
	//res := commands.Root.Call(req)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
61

62 63
	if res.Error() != nil {
		fmt.Println(res.Error().Error())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
64

65 66 67 68
		if cmd.Help != "" && res.Error().Code == cmds.ErrClient {
			// TODO: convert from markdown to ANSI terminal format?
			fmt.Println(cmd.Help)
		}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
69

70
		os.Exit(1)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
71 72
	}

73
	_, err = io.Copy(os.Stdout, res)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
74
	if err != nil {
75
		fmt.Println(err.Error())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
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

func sendRequest(req cmds.Request) (cmds.Response, error) {
	// TODO: load RPC host from config
	url := "http://localhost:8080" + API_PATH
	url += "/" + strings.Join(req.Path(), "/")

	// TODO: support other encodings once we have multicodec to decode response
	//       (we shouldn't have to set this here)
	encoding := cmds.JSON
	req.SetOption(cmds.EncShort, encoding)

	query := "?"
	options := req.Options()
	for k, v := range options {
		query += "&" + k + "=" + v.(string)
	}

	httpRes, err := http.Post(url+query, "application/octet-stream", req.Stream())
	if err != nil {
		return nil, err
	}

	res := cmds.NewResponse(req)

	contentType := httpRes.Header["Content-Type"][0]
	contentType = strings.Split(contentType, ";")[0]

	if contentType == "application/octet-stream" {
		res.SetValue(httpRes.Body)
		return res, nil
	}

	// TODO: decode based on `encoding`, using multicodec
	dec := json.NewDecoder(httpRes.Body)

	if httpRes.StatusCode >= http.StatusBadRequest {
		e := cmds.Error{}
		err = dec.Decode(&e)
		if err != nil {
			fmt.Println(err)
			return nil, err
		}

		res.SetError(e, e.Code)

	} else {
		var v interface{}
		err = dec.Decode(&v)
		if err != nil {
			fmt.Println(err)
			return nil, err
		}

		res.SetValue(v)
	}

	return res, nil
}