diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 1dd5dc369..0e83e9a8a 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -2,16 +2,11 @@ package main import ( "fmt" - "net/http" - "os" - manners "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/braintree/manners" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" - manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" cmds "github.com/jbenet/go-ipfs/commands" - cmdsHttp "github.com/jbenet/go-ipfs/commands/http" - core "github.com/jbenet/go-ipfs/core" commands "github.com/jbenet/go-ipfs/core/commands" + corehttp "github.com/jbenet/go-ipfs/core/corehttp" fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo" util "github.com/jbenet/go-ipfs/util" "github.com/jbenet/go-ipfs/util/debugerror" @@ -24,10 +19,6 @@ const ( ipnsMountKwd = "mount-ipns" // apiAddrKwd = "address-api" // swarmAddrKwd = "address-swarm" - - originEnvKey = "API_ORIGIN" - - webuiPath = "/ipfs/QmTWvqK9dYvqjAMAcCeUun8b45Fwu7wPhEN9B9TsGbkXfJ" ) var daemonCmd = &cmds.Command{ @@ -153,80 +144,17 @@ func daemonFunc(req cmds.Request) (interface{}, error) { if gatewayMaddr != nil { go func() { - err := listenAndServeGateway(node, gatewayMaddr) + err := corehttp.ListenAndServe(node, gatewayMaddr, corehttp.GatewayOption) if err != nil { log.Error(err) } }() } - return nil, listenAndServeAPI(node, req, apiMaddr) -} - -func listenAndServeAPI(node *core.IpfsNode, req cmds.Request, addr ma.Multiaddr) error { - origin := os.Getenv(originEnvKey) - cmdHandler := cmdsHttp.NewHandler(*req.Context(), commands.Root, origin) - gateway, err := NewGatewayHandler(node) - if err != nil { - return err + var opts = []corehttp.ServeOption{ + corehttp.CommandsOption(*req.Context()), + corehttp.WebUIOption, + corehttp.GatewayOption, } - - mux := http.NewServeMux() - mux.Handle(cmdsHttp.ApiPath+"/", cmdHandler) - mux.Handle("/ipfs/", gateway) - mux.Handle("/webui/", &redirectHandler{webuiPath}) - return listenAndServe("API", node, addr, mux) -} - -// the gateway also listens on its own address:port in addition to the API listener -func listenAndServeGateway(node *core.IpfsNode, addr ma.Multiaddr) error { - gateway, err := NewGatewayHandler(node) - if err != nil { - return err - } - - mux := http.NewServeMux() - mux.Handle("/ipfs/", gateway) - return listenAndServe("gateway", node, addr, mux) -} - -func listenAndServe(name string, node *core.IpfsNode, addr ma.Multiaddr, mux *http.ServeMux) error { - _, host, err := manet.DialArgs(addr) - if err != nil { - return err - } - - server := manners.NewServer() - - // if the server exits beforehand - var serverError error - serverExited := make(chan struct{}) - - go func() { - fmt.Printf("%s server listening on %s\n", name, addr) - serverError = server.ListenAndServe(host, mux) - close(serverExited) - }() - - // wait for server to exit. - select { - case <-serverExited: - - // if node being closed before server exits, close server - case <-node.Closing(): - log.Infof("server at %s terminating...", addr) - server.Shutdown <- true - <-serverExited // now, DO wait until server exit - } - - log.Infof("server at %s terminated", addr) - return serverError -} - -type redirectHandler struct { - path string -} - -func (i *redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, i.path, 302) + return nil, corehttp.ListenAndServe(node, apiMaddr, opts...) } diff --git a/core/corehttp/corehttp.go b/core/corehttp/corehttp.go new file mode 100644 index 000000000..14d2d231c --- /dev/null +++ b/core/corehttp/corehttp.go @@ -0,0 +1,100 @@ +package corehttp + +import ( + "fmt" + "net/http" + "os" + + manners "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/braintree/manners" + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" + manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" + commands "github.com/jbenet/go-ipfs/commands" + cmdsHttp "github.com/jbenet/go-ipfs/commands/http" + core "github.com/jbenet/go-ipfs/core" + corecommands "github.com/jbenet/go-ipfs/core/commands" + eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog" +) + +var log = eventlog.Logger("core/server") + +const ( + // TODO rename + originEnvKey = "API_ORIGIN" + webuiPath = "/ipfs/QmTWvqK9dYvqjAMAcCeUun8b45Fwu7wPhEN9B9TsGbkXfJ" +) + +type ServeOption func(*core.IpfsNode, *http.ServeMux) error + +func ListenAndServe(n *core.IpfsNode, addr ma.Multiaddr, options ...ServeOption) error { + mux := http.NewServeMux() + for _, option := range options { + if err := option(n, mux); err != nil { + return err + } + } + return listenAndServe("API", n, addr, mux) +} + +func CommandsOption(cctx commands.Context) ServeOption { + return func(n *core.IpfsNode, mux *http.ServeMux) error { + origin := os.Getenv(originEnvKey) + cmdHandler := cmdsHttp.NewHandler(cctx, corecommands.Root, origin) + mux.Handle(cmdsHttp.ApiPath+"/", cmdHandler) + return nil + } +} + +func GatewayOption(n *core.IpfsNode, mux *http.ServeMux) error { + gateway, err := newGatewayHandler(n) + if err != nil { + return err + } + mux.Handle("/ipfs/", gateway) + return nil +} + +func WebUIOption(n *core.IpfsNode, mux *http.ServeMux) error { + mux.Handle("/webui/", &redirectHandler{webuiPath}) + return nil +} + +func listenAndServe(name string, node *core.IpfsNode, addr ma.Multiaddr, mux *http.ServeMux) error { + _, host, err := manet.DialArgs(addr) + if err != nil { + return err + } + + server := manners.NewServer() + + // if the server exits beforehand + var serverError error + serverExited := make(chan struct{}) + + go func() { + fmt.Printf("%s server listening on %s\n", name, addr) + serverError = server.ListenAndServe(host, mux) + close(serverExited) + }() + + // wait for server to exit. + select { + case <-serverExited: + + // if node being closed before server exits, close server + case <-node.Closing(): + log.Infof("server at %s terminating...", addr) + server.Shutdown <- true + <-serverExited // now, DO wait until server exit + } + + log.Infof("server at %s terminated", addr) + return serverError +} + +type redirectHandler struct { + path string +} + +func (i *redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, i.path, 302) +} diff --git a/cmd/ipfs/gatewayHandler.go b/core/corehttp/gateway_handler.go similarity index 98% rename from cmd/ipfs/gatewayHandler.go rename to core/corehttp/gateway_handler.go index 26422902a..139e7cf20 100644 --- a/cmd/ipfs/gatewayHandler.go +++ b/core/corehttp/gateway_handler.go @@ -1,4 +1,4 @@ -package main +package corehttp import ( "html/template" @@ -42,7 +42,7 @@ type gatewayHandler struct { dirList *template.Template } -func NewGatewayHandler(node *core.IpfsNode) (*gatewayHandler, error) { +func newGatewayHandler(node *core.IpfsNode) (*gatewayHandler, error) { i := &gatewayHandler{ node: node, }