From 0e042b5c808566278be427cba1f14c26bda87f3c Mon Sep 17 00:00:00 2001 From: Lars Gierth Date: Sun, 11 Sep 2016 05:18:25 +0200 Subject: [PATCH] gateway: use core api for serving GET/HEAD requests License: MIT Signed-off-by: Lars Gierth --- core/corehttp/gateway.go | 5 ++-- core/corehttp/gateway_handler.go | 49 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index 9a8fd005d440..b306c550fffd 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -6,6 +6,7 @@ import ( "net/http" core "github.com/ipfs/go-ipfs/core" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" config "github.com/ipfs/go-ipfs/repo/config" id "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/protocol/identify" ) @@ -27,7 +28,7 @@ func GatewayOption(writable bool, paths ...string) ServeOption { Headers: cfg.Gateway.HTTPHeaders, Writable: writable, PathPrefixes: cfg.Gateway.PathPrefixes, - }) + }, coreapi.NewUnixfsAPI(n)) for _, p := range paths { mux.Handle(p+"/", gateway) @@ -37,7 +38,7 @@ func GatewayOption(writable bool, paths ...string) ServeOption { } func VersionOption() ServeOption { - return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { + return func(_ *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Commit: %s\n", config.CurrentCommit) fmt.Fprintf(w, "Client Version: %s\n", id.ClientVersion) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 659d847b3f1f..ca10bef60d50 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -19,6 +19,8 @@ import ( chunk "github.com/ipfs/go-ipfs/importer/chunk" dag "github.com/ipfs/go-ipfs/merkledag" dagutils "github.com/ipfs/go-ipfs/merkledag/utils" + + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" path "github.com/ipfs/go-ipfs/path" "github.com/ipfs/go-ipfs/routing" uio "github.com/ipfs/go-ipfs/unixfs/io" @@ -34,12 +36,14 @@ const ( type gatewayHandler struct { node *core.IpfsNode config GatewayConfig + api coreiface.UnixfsAPI } -func newGatewayHandler(node *core.IpfsNode, conf GatewayConfig) *gatewayHandler { +func newGatewayHandler(n *core.IpfsNode, c GatewayConfig, api coreiface.UnixfsAPI) *gatewayHandler { i := &gatewayHandler{ - node: node, - config: conf, + node: n, + config: c, + api: api, } return i } @@ -78,7 +82,7 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if r.Method == "GET" || r.Method == "HEAD" { - i.getOrHeadHandler(w, r) + i.getOrHeadHandler(w, r, i.api) return } @@ -108,7 +112,7 @@ func (i *gatewayHandler) optionsHandler(w http.ResponseWriter, r *http.Request) i.addUserHeaders(w) // return all custom headers (including CORS ones, if set) } -func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { +func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request, api coreiface.UnixfsAPI) { ctx, cancel := context.WithTimeout(i.node.Context(), time.Hour) // the hour is a hard fallback, we don't expect it to happen, but just in case defer cancel() @@ -152,15 +156,19 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request ipnsHostname = true } - nd, err := core.Resolve(ctx, i.node, path.Path(urlPath)) - // If node is in offline mode the error code and message should be different - if err == core.ErrNoNamesys && !i.node.OnlineMode() { + dr, err := api.Cat(ctx, urlPath) + dir := false + if err == coreiface.ErrOffline { w.WriteHeader(http.StatusServiceUnavailable) fmt.Fprint(w, "Could not resolve path. Node is in offline mode.") return + } else if err == coreiface.ErrIsDir { + dir = true } else if err != nil { webError(w, "Path Resolve error", err, http.StatusBadRequest) return + } else { + defer dr.Close() } etag := gopath.Base(urlPath) @@ -190,13 +198,6 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request w.Header().Set("Suborigin", pathRoot) } - dr, err := uio.NewDagReader(ctx, nd, i.node.DAG) - if err != nil && err != uio.ErrIsDir { - // not a directory and still an error - internalWebError(w, err) - return - } - // set these headers _after_ the error, for we may just not have it // and dont want the client to cache a 500 response... // and only if it's /ipfs! @@ -210,18 +211,23 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request modtime = time.Unix(1, 0) } - if err == nil { - defer dr.Close() + if !dir { name := gopath.Base(urlPath) http.ServeContent(w, r, name, modtime, dr) return } + links, err := api.Ls(ctx, urlPath) + if err != nil { + internalWebError(w, err) + return + } + // storage for directory listing var dirListing []directoryItem // loop through files foundIndex := false - for _, link := range nd.Links { + for _, link := range links { if link.Name == "index.html" { log.Debugf("found index.html link for %s", urlPath) foundIndex = true @@ -234,12 +240,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request } // return index page instead. - nd, err := core.Resolve(ctx, i.node, path.Path(urlPath+"/index.html")) - if err != nil { - internalWebError(w, err) - return - } - dr, err := uio.NewDagReader(ctx, nd, i.node.DAG) + dr, err := api.Cat(ctx, urlPath+"/index.html") if err != nil { internalWebError(w, err) return