From 0bb6c111bbe73354ecdca4f885c094f678eaa8dd Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 10 Apr 2015 02:12:17 -0700 Subject: [PATCH] ServeFile --- cmd/debora/main.go | 37 +++++++++++++++++++++++++++++----- node/node.go | 8 +++++++- process/process.go | 49 ++++++++++++++++++++++++++-------------------- rpc/http_server.go | 8 +------- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/cmd/debora/main.go b/cmd/debora/main.go index 5718f86e..5eb4ddde 100644 --- a/cmd/debora/main.go +++ b/cmd/debora/main.go @@ -2,7 +2,9 @@ package main import ( "fmt" + "io" "io/ioutil" + "net/http" "os" "sync" @@ -10,13 +12,15 @@ import ( "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" pcm "github.com/tendermint/tendermint/process" - rpc "github.com/tendermint/tendermint/rpc" + "github.com/tendermint/tendermint/rpc" ) var Routes = map[string]*rpc.RPCFunc{ "RunProcess": rpc.NewRPCFunc(RunProcess, []string{"wait", "label", "execPath", "args"}), "ListProcesses": rpc.NewRPCFunc(ListProcesses, []string{}), "StopProcess": rpc.NewRPCFunc(StopProcess, []string{"label", "kill"}), + // NOTE: also, two special non-JSONRPC routes called + // "download" and "upload". } type Validator struct { @@ -52,8 +56,11 @@ func main() { fmt.Printf("Validators: %v\n", options.Validators) // start rpc server. - fmt.Println("Listening HTTP-JSONRPC on", options.ListenAddress) - rpc.StartHTTPServer(options.ListenAddress, Routes, nil) + mux := http.NewServeMux() + mux.HandleFunc("/download", ServeFile) + // TODO: mux.HandleFunc("/upload", UploadFile) + rpc.RegisterRPCFuncs(mux, Routes) + rpc.StartHTTPServer(options.ListenAddress, mux) TrapSignal(func() { fmt.Println("Debora shutting down") @@ -66,7 +73,7 @@ func main() { type ResponseRunProcess struct { } -func RunProcess(wait bool, label string, execPath string, args []string) (*ResponseRunProcess, error) { +func RunProcess(wait bool, label string, execPath string, args []string, input string) (*ResponseRunProcess, error) { debora.mtx.Lock() // First, see if there already is a process labeled 'label' @@ -77,7 +84,7 @@ func RunProcess(wait bool, label string, execPath string, args []string) (*Respo } // Otherwise, create one. - proc := pcm.Create(pcm.ProcessModeDaemon, label, execPath, args...) + proc := pcm.Create(pcm.ProcessModeDaemon, label, execPath, args, input) debora.processes[label] = proc debora.mtx.Unlock() @@ -125,3 +132,23 @@ func StopProcess(label string, kill bool) (*ResponseStopProcess, error) { err := pcm.Stop(proc, kill) return &ResponseStopProcess{}, err } + +//------------------------------------------------------------------------------ + +func ServeFile(w http.ResponseWriter, req *http.Request) { + path := req.FormValue("path") + if path == "" { + http.Error(w, "Must specify path", 400) + return + } + file, err := os.Open(path) + if err != nil { + http.Error(w, Fmt("Error opening file: %v. %v", path, err), 400) + return + } + _, err = io.Copy(w, file) + if err != nil { + fmt.Fprintf(os.Stderr, Fmt("Error serving file: %v. %v", path, err)) + return + } +} diff --git a/node/node.go b/node/node.go index 53141340..f7749a80 100644 --- a/node/node.go +++ b/node/node.go @@ -1,6 +1,7 @@ package node import ( + "net/http" "os" bc "github.com/tendermint/tendermint/blockchain" @@ -146,7 +147,12 @@ func (n *Node) StartRPC() { core.SetConsensusState(n.consensusState) core.SetMempoolReactor(n.mempoolReactor) core.SetSwitch(n.sw) - rpc.StartHTTPServer(config.App().GetString("RPC.HTTP.ListenAddr"), core.Routes, n.evsw) + + listenAddr := config.App().GetString("RPC.HTTP.ListenAddr") + mux := http.NewServeMux() + rpc.RegisterEventsHandler(mux, n.evsw) + rpc.RegisterRPCFuncs(mux, core.Routes) + rpc.StartHTTPServer(listenAddr, mux) } func (n *Node) Switch() *p2p.Switch { diff --git a/process/process.go b/process/process.go index f7994940..4582a2a0 100644 --- a/process/process.go +++ b/process/process.go @@ -1,6 +1,7 @@ package process import ( + "bytes" "fmt" "io" "os" @@ -8,23 +9,24 @@ import ( "time" ) -func makeFile(prefix string) *os.File { +func makeFile(prefix string) (string, *os.File) { now := time.Now() - filename := fmt.Sprintf("%v_%v.out", prefix, now.Format("2006_01_02_15_04_05_MST")) - f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + path := fmt.Sprintf("%v_%v.out", prefix, now.Format("2006_01_02_15_04_05_MST")) + file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic(err) } - return f + return path, file } type Process struct { - Label string - ExecPath string - StartTime time.Time - Cmd *exec.Cmd `json:"-"` - Output *os.File `json:"-"` - ExitState *os.ProcessState `json:"-"` + Label string + ExecPath string + StartTime time.Time + OutputPath string + Cmd *exec.Cmd `json:"-"` + ExitState *os.ProcessState `json:"-"` + OutputFile *os.File `json:"-"` } const ( @@ -34,19 +36,22 @@ const ( // execPath: command name // args: args to command. (should not include name) -func Create(mode int, label string, execPath string, args ...string) *Process { - out := makeFile(label) +func Create(mode int, label string, execPath string, args []string, input string) *Process { + outPath, outFile := makeFile(label) cmd := exec.Command(execPath, args...) switch mode { case ProcessModeStd: - cmd.Stdout = io.MultiWriter(os.Stdout, out) - cmd.Stderr = io.MultiWriter(os.Stderr, out) + cmd.Stdout = io.MultiWriter(os.Stdout, outFile) + cmd.Stderr = io.MultiWriter(os.Stderr, outFile) cmd.Stdin = nil case ProcessModeDaemon: - cmd.Stdout = out - cmd.Stderr = out + cmd.Stdout = outFile + cmd.Stderr = outFile cmd.Stdin = nil } + if input != "" { + cmd.Stdin = bytes.NewReader([]byte(input)) + } if err := cmd.Start(); err != nil { fmt.Printf("Failed to run command. %v\n", err) return nil @@ -54,11 +59,13 @@ func Create(mode int, label string, execPath string, args ...string) *Process { fmt.Printf("Success!") } return &Process{ - Label: label, - ExecPath: execPath, - StartTime: time.Now(), - Cmd: cmd, - Output: out, + Label: label, + ExecPath: execPath, + StartTime: time.Now(), + OutputPath: outPath, + Cmd: cmd, + ExitState: nil, + OutputFile: outFile, } } diff --git a/rpc/http_server.go b/rpc/http_server.go index 2defdf5d..03f80544 100644 --- a/rpc/http_server.go +++ b/rpc/http_server.go @@ -10,16 +10,10 @@ import ( "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/events" ) -func StartHTTPServer(listenAddr string, funcMap map[string]*RPCFunc, evsw *events.EventSwitch) { +func StartHTTPServer(listenAddr string, mux *http.ServeMux) { log.Info(Fmt("Starting RPC HTTP server on %s", listenAddr)) - mux := http.NewServeMux() - RegisterRPCFuncs(mux, funcMap) - if evsw != nil { - RegisterEventsHandler(mux, evsw) - } go func() { res := http.ListenAndServe( listenAddr,