From 9917eb3939b3a17fdc199f29913dbe0c55110fad 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 | 66 +++++++++++--------------------- 2 files changed, 26 insertions(+), 45 deletions(-) diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index 4aa26fed751..4214679411d 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/QmcRa2qn6iCmap9bjp8jAwkvYAq13AUfxdY3rrYiaJbLum/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 c35431cbe31..1adc079c89e 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -16,9 +16,10 @@ 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" ft "github.com/ipfs/go-ipfs/unixfs" - uio "github.com/ipfs/go-ipfs/unixfs/io" humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" routing "gx/ipfs/QmQKEgGgYCDyk8VNY6A65FpuE4YwbspvjXHco1rdb75PVc/go-libp2p-routing" @@ -36,12 +37,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 } @@ -122,7 +125,6 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request case <-clientGone: case <-ctx.Done(): } - cancel() }() } @@ -154,27 +156,19 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request ipnsHostname = true } - p, err := path.ParsePath(urlPath) - if err != nil { - webError(w, "Invalid Path Error", err, http.StatusBadRequest) - return - } - - nd, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, p) - // If node is in offline mode the error code and message should be different - if err == core.ErrNoNamesys && !i.node.OnlineMode() { + dr, err := i.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 - } - - pbnd, ok := nd.(*dag.ProtoNode) - if !ok { - webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest) - return + } else { + defer dr.Close() } etag := gopath.Base(urlPath) @@ -204,13 +198,6 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request w.Header().Set("Suborigin", pathRoot) } - dr, err := uio.NewDagReader(ctx, pbnd, 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! @@ -224,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 := i.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 @@ -254,19 +246,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request } // return index page instead. - nd, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, p) - if err != nil { - internalWebError(w, err) - return - } - - pbnd, ok := nd.(*dag.ProtoNode) - if !ok { - internalWebError(w, dag.ErrNotProtobuf) - return - } - - dr, err := uio.NewDagReader(ctx, pbnd, i.node.DAG) + dr, err := i.api.Cat(ctx, p.String()) if err != nil { internalWebError(w, err) return