Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa7b637

Browse files
committedNov 3, 2015
writableGW: passing non-meaningful tests
License: MIT Signed-off-by: Henry <cryptix@riseup.net>
1 parent d251b34 commit aa7b637

File tree

1 file changed

+54
-96
lines changed

1 file changed

+54
-96
lines changed
 

‎core/corehttp/gateway_handler.go

+54-96
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,20 @@ func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
5555

5656
// TODO(btc): break this apart into separate handlers using a more expressive muxer
5757
func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
58+
ctx, cancel := context.WithCancel(i.node.Context())
59+
defer cancel()
60+
5861
if i.config.Writable {
5962
switch r.Method {
6063
case "POST":
61-
i.postHandler(w, r)
64+
i.postHandler(ctx, w, r)
6265
return
6366
case "PUT":
64-
i.putHandler(w, r)
67+
// TODO(cryptix): where are the docs?
68+
http.Error(w, "writableGateway: PUT method not meaningful on IPFS - use POST and see the docs", http.StatusMethodNotAllowed)
6569
return
6670
case "DELETE":
67-
i.deleteHandler(w, r)
71+
i.deleteHandler(ctx, w, r)
6872
return
6973
}
7074
}
@@ -97,11 +101,11 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
97101
// and links that match the requested URL.
98102
// For example, http://example.net would become /ipns/example.net, and
99103
// the redirects and links would end up as http://example.net/ipns/example.net
100-
originalUrlPath := urlPath
104+
originalURLPath := urlPath
101105
ipnsHostname := false
102106
hdr := r.Header["X-IPNS-Original-Path"]
103107
if len(hdr) > 0 {
104-
originalUrlPath = hdr[0]
108+
originalURLPath = hdr[0]
105109
ipnsHostname = true
106110
}
107111

@@ -176,9 +180,9 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
176180
foundIndex = true
177181

178182
if urlPath[len(urlPath)-1] != '/' {
179-
// See comment above where originalUrlPath is declared.
180-
http.Redirect(w, r, originalUrlPath+"/", 302)
181-
log.Debugf("redirect to %s", originalUrlPath+"/")
183+
// See comment above where originalURLPath is declared.
184+
http.Redirect(w, r, originalURLPath+"/", 302)
185+
log.Debugf("redirect to %s", originalURLPath+"/")
182186
return
183187
}
184188

@@ -202,16 +206,16 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
202206
break
203207
}
204208

205-
// See comment above where originalUrlPath is declared.
206-
di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)}
209+
// See comment above where originalURLPath is declared.
210+
di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalURLPath, link.Name)}
207211
dirListing = append(dirListing, di)
208212
}
209213

210214
if !foundIndex {
211215
if r.Method != "HEAD" {
212216
// construct the correct back link
213217
// https://github.com/ipfs/go-ipfs/issues/1365
214-
var backLink string = urlPath
218+
var backLink = urlPath
215219

216220
// don't go further up than /ipfs/$hash/
217221
pathSplit := strings.Split(backLink, "/")
@@ -241,10 +245,10 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
241245
}
242246
}
243247

244-
// See comment above where originalUrlPath is declared.
248+
// See comment above where originalURLPath is declared.
245249
tplData := listingTemplateData{
246250
Listing: dirListing,
247-
Path: originalUrlPath,
251+
Path: originalURLPath,
248252
BackLink: backLink,
249253
}
250254
err := listingTemplate.Execute(w, tplData)
@@ -256,38 +260,16 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
256260
}
257261
}
258262

259-
func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
260-
nd, err := i.newDagFromReader(r.Body)
261-
if err != nil {
262-
internalWebError(w, err)
263-
return
264-
}
265-
266-
k, err := i.node.DAG.Add(nd)
267-
if err != nil {
268-
internalWebError(w, err)
269-
return
270-
}
271-
272-
i.addUserHeaders(w) // ok, _now_ write user's headers.
273-
w.Header().Set("IPFS-Hash", k.String())
274-
http.Redirect(w, r, ipfsPathPrefix+k.String(), http.StatusCreated)
275-
}
276-
277-
func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
278-
// TODO(cryptix): move me to ServeHTTP and pass into all handlers
279-
ctx, cancel := context.WithCancel(i.node.Context())
280-
defer cancel()
281-
263+
func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
282264
rootPath, err := path.ParsePath(r.URL.Path)
283265
if err != nil {
284-
webError(w, "putHandler: ipfs path not valid", err, http.StatusBadRequest)
266+
webError(w, "postHandler: ipfs path not valid", err, http.StatusBadRequest)
285267
return
286268
}
287269

288270
rsegs := rootPath.Segments()
289271
if rsegs[0] == ipnsPathPrefix {
290-
webError(w, "putHandler: updating named entries not supported", errors.New("WritableGateway: ipns put not supported"), http.StatusBadRequest)
272+
webError(w, "postHandler: updating named entries not supported", ErrIPNSNotSupported, http.StatusBadRequest)
291273
return
292274
}
293275

@@ -297,15 +279,15 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
297279
} else {
298280
putNode, err := i.newDagFromReader(r.Body)
299281
if err != nil {
300-
webError(w, "putHandler: Could not create DAG from request", err, http.StatusInternalServerError)
282+
webError(w, "postHandler: Could not create DAG from request", err, http.StatusInternalServerError)
301283
return
302284
}
303285
newnode = putNode
304286
}
305287

306288
var newPath string
307289
if len(rsegs) > 1 {
308-
newPath = strings.Join(rsegs[2:], "/")
290+
newPath = gopath.Join(rsegs[2:]...)
309291
}
310292

311293
var newkey key.Key
@@ -317,20 +299,20 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
317299
// but we need to patch from the root
318300
rnode, err := i.node.DAG.Get(ctx, key.B58KeyDecode(rsegs[1]))
319301
if err != nil {
320-
webError(w, "putHandler: Could not create DAG from request", err, http.StatusInternalServerError)
302+
webError(w, "postHandler: Could not create DAG from request", err, http.StatusInternalServerError)
321303
return
322304
}
323305

324306
e := dagutils.NewDagEditor(i.node.DAG, rnode)
325307
err = e.InsertNodeAtPath(ctx, newPath, newnode, uio.NewEmptyDirectory)
326308
if err != nil {
327-
webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
309+
webError(w, "postHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
328310
return
329311
}
330312

331313
newkey, err = e.GetNode().Key()
332314
if err != nil {
333-
webError(w, "putHandler: could not get key of edited node", err, http.StatusInternalServerError)
315+
webError(w, "postHandler: could not get key of edited node", err, http.StatusInternalServerError)
334316
return
335317
}
336318

@@ -342,11 +324,11 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
342324
if err != nil {
343325
nnk, _ := newnode.Key()
344326
rk, _ := rnode.Key()
345-
webError(w, fmt.Sprintf("putHandler: Could not add newnode(%q) to root(%q)", nnk.B58String(), rk.B58String()), err, http.StatusInternalServerError)
327+
webError(w, fmt.Sprintf("postHandler: Could not add newnode(%q) to root(%q)", nnk.B58String(), rk.B58String()), err, http.StatusInternalServerError)
346328
return
347329
}
348330
default:
349-
log.Warningf("putHandler: unhandled resolve error %T", ev)
331+
log.Warningf("postHandler: unhandled resolve error %T", ev)
350332
webError(w, "could not resolve root DAG", ev, http.StatusInternalServerError)
351333
return
352334
}
@@ -356,81 +338,56 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
356338
http.Redirect(w, r, gopath.Join(ipfsPathPrefix, newkey.String(), newPath), http.StatusCreated)
357339
}
358340

359-
func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
360-
urlPath := r.URL.Path
361-
ctx, cancel := context.WithCancel(i.node.Context())
362-
defer cancel()
363-
364-
ipfsNode, err := core.Resolve(ctx, i.node, path.Path(urlPath))
365-
if err != nil {
366-
// FIXME HTTP error code
367-
webError(w, "Could not resolve name", err, http.StatusInternalServerError)
368-
return
369-
}
370-
371-
k, err := ipfsNode.Key()
372-
if err != nil {
373-
webError(w, "Could not get key from resolved node", err, http.StatusInternalServerError)
374-
return
375-
}
341+
var (
342+
ErrIPNSNotSupported = errors.New("writableGateway: /ipns/ not supported")
343+
ErrNotMeaningfulOnWritable = errors.New("writableGateway: non-meaningful request")
344+
)
376345

377-
h, components, err := path.SplitAbsPath(path.FromKey(k))
378-
if err != nil {
379-
webError(w, "Could not split path", err, http.StatusInternalServerError)
346+
func (i *gatewayHandler) deleteHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
347+
if r.URL.Path == "/ipfs" || r.URL.Path == ipfsPathPrefix {
348+
webErrorWithCode(w, "HTTP DELETE of /ipfs is not meaningful", ErrNotMeaningfulOnWritable, http.StatusMethodNotAllowed)
380349
return
381350
}
382351

383-
tctx, cancel := context.WithTimeout(ctx, time.Minute)
384-
defer cancel()
385-
rootnd, err := i.node.Resolver.DAG.Get(tctx, key.Key(h))
352+
rootPath, err := path.ParsePath(r.URL.Path)
386353
if err != nil {
387-
webError(w, "Could not resolve root object", err, http.StatusBadRequest)
354+
webError(w, "deleteHandler: ipfs path not valid", err, http.StatusBadRequest)
388355
return
389356
}
390357

391-
// catches handler panic
392-
if len(components) == 0 {
393-
webError(w, "delete request not meaningful", fmt.Errorf("deleteHandler: empty path. %q", urlPath), http.StatusMethodNotAllowed)
358+
rsegs := rootPath.Segments()
359+
if rsegs[0] == ipnsPathPrefix {
360+
webError(w, "deleteHandler: updating named entries not supported", ErrIPNSNotSupported, http.StatusBadRequest)
394361
return
395362
}
396363

397-
pathNodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1])
398-
if err != nil {
399-
webError(w, "Could not resolve parent object", err, http.StatusBadRequest)
400-
return
364+
if len(rsegs) == 2 { // /ipfs/$hash
365+
webErrorWithCode(w, "HTTP DELETE of /ipfs/$hash is not meaningful", ErrNotMeaningfulOnWritable, http.StatusMethodNotAllowed)
401366
}
402367

403-
// TODO(cyrptix): assumes len(pathNodes) > 1 - not found is an error above?
404-
err = pathNodes[len(pathNodes)-1].RemoveNodeLink(components[len(components)-1])
368+
rnode, err := i.node.DAG.Get(ctx, key.B58KeyDecode(rsegs[1]))
405369
if err != nil {
406-
webError(w, "Could not delete link", err, http.StatusBadRequest)
370+
webError(w, "deleteHandler: Could not create DAG from request", err, http.StatusInternalServerError)
407371
return
408372
}
409373

410-
newnode := pathNodes[len(pathNodes)-1]
411-
for i := len(pathNodes) - 2; i >= 0; i-- {
412-
newnode, err = pathNodes[i].UpdateNodeLink(components[i], newnode)
413-
if err != nil {
414-
webError(w, "Could not update node links", err, http.StatusInternalServerError)
415-
return
416-
}
417-
}
374+
newPath := gopath.Join(rsegs[2:]...)
418375

419-
if err := i.node.DAG.AddRecursive(newnode); err != nil {
420-
webError(w, "Could not add recursively new node", err, http.StatusInternalServerError)
376+
e := dagutils.NewDagEditor(i.node.DAG, rnode)
377+
if err := e.RmLink(ctx, newPath); err != nil {
378+
webError(w, "deleteHandler: dag editor failed to rmLink()", err, http.StatusInternalServerError)
421379
return
422380
}
423381

424-
// Redirect to new path
425-
key, err := newnode.Key()
382+
newkey, err := e.GetNode().Key()
426383
if err != nil {
427-
webError(w, "Could not get key of new node", err, http.StatusInternalServerError)
384+
webError(w, "deleteHandler: could not get key of edited node", err, http.StatusInternalServerError)
428385
return
429386
}
430387

431388
i.addUserHeaders(w) // ok, _now_ write user's headers.
432-
w.Header().Set("IPFS-Hash", key.String())
433-
http.Redirect(w, r, ipfsPathPrefix+key.String()+"/"+strings.Join(components[:len(components)-1], "/"), http.StatusCreated)
389+
w.Header().Set("IPFS-Hash", newkey.String())
390+
http.Redirect(w, r, gopath.Join(ipfsPathPrefix, newkey.String(), newPath), http.StatusCreated)
434391
}
435392

436393
func (i *gatewayHandler) addUserHeaders(w http.ResponseWriter) {
@@ -453,8 +410,9 @@ func webError(w http.ResponseWriter, message string, err error, defaultCode int)
453410

454411
func webErrorWithCode(w http.ResponseWriter, message string, err error, code int) {
455412
w.WriteHeader(code)
456-
log.Errorf("%s: %s", message, err) // TODO(cryptix): log errors until we have a better way to expose these (counter metrics maybe)
457-
fmt.Fprintf(w, "%s: %s", message, err)
413+
s := fmt.Sprintf("%s: %s", message, err)
414+
log.Errorf(s) // TODO(cryptix): log errors until we have a better way to expose these (counter metrics maybe)
415+
fmt.Fprint(w, s)
458416
}
459417

460418
// return a 500 error and log

0 commit comments

Comments
 (0)
Please sign in to comment.