Skip to content

Commit

Permalink
Merge pull request #6244 from reinerRubin/fix/core/4607-pass-context
Browse files Browse the repository at this point in the history
core/corehttp/gateway_handler: pass a request ctx instead of the node
  • Loading branch information
Stebalien committed Apr 23, 2019
2 parents f4f64ef + d2836de commit fc4dbb6
Showing 1 changed file with 41 additions and 33 deletions.
74 changes: 41 additions & 33 deletions core/corehttp/gateway_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"github.com/dustin/go-humanize"
"github.com/ipfs/go-cid"
chunker "github.com/ipfs/go-ipfs-chunker"
"github.com/ipfs/go-ipfs-files"
files "github.com/ipfs/go-ipfs-files"
ipld "github.com/ipfs/go-ipld-format"
dag "github.com/ipfs/go-merkledag"
"github.com/ipfs/go-path"
Expand All @@ -28,7 +28,7 @@ import (
"github.com/ipfs/go-unixfs/importer"
coreiface "github.com/ipfs/interface-go-ipfs-core"
ipath "github.com/ipfs/interface-go-ipfs-core/path"
"github.com/libp2p/go-libp2p-routing"
routing "github.com/libp2p/go-libp2p-routing"
"github.com/multiformats/go-multibase"
)

Expand Down Expand Up @@ -67,6 +67,7 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// the hour is a hard fallback, we don't expect it to happen, but just in case
ctx, cancel := context.WithTimeout(r.Context(), time.Hour)
defer cancel()
r = r.WithContext(ctx)

defer func() {
if r := recover(); r != nil {
Expand All @@ -79,7 +80,7 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if i.config.Writable {
switch r.Method {
case "POST":
i.postHandler(ctx, w, r)
i.postHandler(w, r)
return
case "PUT":
i.putHandler(w, r)
Expand All @@ -91,7 +92,7 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

if r.Method == "GET" || r.Method == "HEAD" {
i.getOrHeadHandler(ctx, w, r)
i.getOrHeadHandler(w, r)
return
}

Expand Down Expand Up @@ -120,7 +121,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(ctx context.Context, w http.ResponseWriter, r *http.Request) {
func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
escapedURLPath := r.URL.EscapedPath()

Expand Down Expand Up @@ -156,7 +157,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
}

// Resolve path to the final DAG node for the ETag
resolvedPath, err := i.api.ResolvePath(ctx, parsedPath)
resolvedPath, err := i.api.ResolvePath(r.Context(), parsedPath)
if err == coreiface.ErrOffline && !i.node.IsOnline {
webError(w, "ipfs resolve -r "+escapedURLPath, err, http.StatusServiceUnavailable)
return
Expand All @@ -165,7 +166,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
return
}

dr, err := i.api.Unixfs().Get(ctx, resolvedPath)
dr, err := i.api.Unixfs().Get(r.Context(), resolvedPath)
if err != nil {
webError(w, "ipfs cat "+escapedURLPath, err, http.StatusNotFound)
return
Expand Down Expand Up @@ -248,7 +249,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
return
}

idx, err := i.api.Unixfs().Get(ctx, ipath.Join(resolvedPath, "index.html"))
idx, err := i.api.Unixfs().Get(r.Context(), ipath.Join(resolvedPath, "index.html"))
switch err.(type) {
case nil:
dirwithoutslash := urlPath[len(urlPath)-1] != '/'
Expand Down Expand Up @@ -377,8 +378,8 @@ func (i *gatewayHandler) serveFile(w http.ResponseWriter, req *http.Request, nam
http.ServeContent(w, req, name, modtime, content)
}

func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
p, err := i.api.Unixfs().Add(ctx, files.NewReaderFile(r.Body))
func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
p, err := i.api.Unixfs().Add(r.Context(), files.NewReaderFile(r.Body))
if err != nil {
internalWebError(w, err)
return
Expand All @@ -390,10 +391,6 @@ func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter,
}

func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
// TODO(cryptix): move me to ServeHTTP and pass into all handlers
ctx, cancel := context.WithCancel(i.node.Context())
defer cancel()

rootPath, err := path.ParsePath(r.URL.Path)
if err != nil {
webError(w, "putHandler: IPFS path not valid", err, http.StatusBadRequest)
Expand Down Expand Up @@ -424,7 +421,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
}

var newcid cid.Cid
rnode, err := resolve.Resolve(ctx, i.node.Namesys, i.node.Resolver, rootPath)
rnode, err := resolve.Resolve(r.Context(), i.node.Namesys, i.node.Resolver, rootPath)
switch ev := err.(type) {
case resolver.ErrNoLink:
// ev.Node < node where resolve failed
Expand All @@ -436,7 +433,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
return
}

rnode, err := i.node.DAG.Get(ctx, c)
rnode, err := i.node.DAG.Get(r.Context(), c)
if err != nil {
webError(w, "putHandler: Could not create DAG from request", err, http.StatusInternalServerError)
return
Expand All @@ -449,13 +446,13 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
}

e := dagutils.NewDagEditor(pbnd, i.node.DAG)
err = e.InsertNodeAtPath(ctx, newPath, newnode, ft.EmptyDirNode)
err = e.InsertNodeAtPath(r.Context(), newPath, newnode, ft.EmptyDirNode)
if err != nil {
webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
return
}

nnode, err := e.Finalize(ctx, i.node.DAG)
nnode, err := e.Finalize(r.Context(), i.node.DAG)
if err != nil {
webError(w, "putHandler: could not get node", err, http.StatusInternalServerError)
return
Expand All @@ -480,7 +477,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
pbnd.SetData(pbnewnode.Data())

newcid = pbnd.Cid()
err = i.node.DAG.Add(ctx, pbnd)
err = i.node.DAG.Add(r.Context(), pbnd)
if err != nil {
nnk := newnode.Cid()
webError(w, fmt.Sprintf("putHandler: Could not add newnode(%q) to root(%q)", nnk.String(), newcid.String()), err, http.StatusInternalServerError)
Expand All @@ -498,8 +495,6 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {

func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
ctx, cancel := context.WithCancel(i.node.Context())
defer cancel()

p, err := path.ParsePath(urlPath)
if err != nil {
Expand All @@ -513,17 +508,9 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
return
}

tctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
rootnd, err := i.node.Resolver.DAG.Get(tctx, c)
if err != nil {
webError(w, "Could not resolve root object", err, http.StatusBadRequest)
return
}

pathNodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1])
pathNodes, err := i.resolvePathComponents(r.Context(), c, components)
if err != nil {
webError(w, "Could not resolve parent object", err, http.StatusBadRequest)
webError(w, "Could not resolve path components", err, http.StatusBadRequest)
return
}

Expand All @@ -542,7 +529,7 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {

var newnode *dag.ProtoNode = pbnd
for j := len(pathNodes) - 2; j >= 0; j-- {
if err := i.node.DAG.Add(ctx, newnode); err != nil {
if err := i.node.DAG.Add(r.Context(), newnode); err != nil {
webError(w, "Could not add node", err, http.StatusInternalServerError)
return
}
Expand All @@ -560,7 +547,7 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
}
}

if err := i.node.DAG.Add(ctx, newnode); err != nil {
if err := i.node.DAG.Add(r.Context(), newnode); err != nil {
webError(w, "Could not add root node", err, http.StatusInternalServerError)
return
}
Expand All @@ -573,6 +560,27 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, gopath.Join(ipfsPathPrefix+ncid.String(), path.Join(components[:len(components)-1])), http.StatusCreated)
}

func (i *gatewayHandler) resolvePathComponents(
ctx context.Context,
c cid.Cid,
components []string,
) ([]ipld.Node, error) {
tctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()

rootnd, err := i.node.Resolver.DAG.Get(tctx, c)
if err != nil {
return nil, fmt.Errorf("Could not resolve root object: %s", err)
}

pathNodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1])
if err != nil {
return nil, fmt.Errorf("Could not resolve parent object: %s", err)
}

return pathNodes, nil
}

func (i *gatewayHandler) addUserHeaders(w http.ResponseWriter) {
for k, v := range i.config.Headers {
w.Header()[k] = v
Expand Down

0 comments on commit fc4dbb6

Please sign in to comment.