@@ -55,16 +55,20 @@ func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
55
55
56
56
// TODO(btc): break this apart into separate handlers using a more expressive muxer
57
57
func (i * gatewayHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
58
+ ctx , cancel := context .WithCancel (i .node .Context ())
59
+ defer cancel ()
60
+
58
61
if i .config .Writable {
59
62
switch r .Method {
60
63
case "POST" :
61
- i .postHandler (w , r )
64
+ i .postHandler (ctx , w , r )
62
65
return
63
66
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 )
65
69
return
66
70
case "DELETE" :
67
- i .deleteHandler (w , r )
71
+ i .deleteHandler (ctx , w , r )
68
72
return
69
73
}
70
74
}
@@ -97,11 +101,11 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
97
101
// and links that match the requested URL.
98
102
// For example, http://example.net would become /ipns/example.net, and
99
103
// the redirects and links would end up as http://example.net/ipns/example.net
100
- originalUrlPath := urlPath
104
+ originalURLPath := urlPath
101
105
ipnsHostname := false
102
106
hdr := r .Header ["X-IPNS-Original-Path" ]
103
107
if len (hdr ) > 0 {
104
- originalUrlPath = hdr [0 ]
108
+ originalURLPath = hdr [0 ]
105
109
ipnsHostname = true
106
110
}
107
111
@@ -176,9 +180,9 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
176
180
foundIndex = true
177
181
178
182
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 + "/" )
182
186
return
183
187
}
184
188
@@ -202,16 +206,16 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
202
206
break
203
207
}
204
208
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 )}
207
211
dirListing = append (dirListing , di )
208
212
}
209
213
210
214
if ! foundIndex {
211
215
if r .Method != "HEAD" {
212
216
// construct the correct back link
213
217
// https://github.com/ipfs/go-ipfs/issues/1365
214
- var backLink string = urlPath
218
+ var backLink = urlPath
215
219
216
220
// don't go further up than /ipfs/$hash/
217
221
pathSplit := strings .Split (backLink , "/" )
@@ -241,10 +245,10 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
241
245
}
242
246
}
243
247
244
- // See comment above where originalUrlPath is declared.
248
+ // See comment above where originalURLPath is declared.
245
249
tplData := listingTemplateData {
246
250
Listing : dirListing ,
247
- Path : originalUrlPath ,
251
+ Path : originalURLPath ,
248
252
BackLink : backLink ,
249
253
}
250
254
err := listingTemplate .Execute (w , tplData )
@@ -256,38 +260,16 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
256
260
}
257
261
}
258
262
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 ) {
282
264
rootPath , err := path .ParsePath (r .URL .Path )
283
265
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 )
285
267
return
286
268
}
287
269
288
270
rsegs := rootPath .Segments ()
289
271
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 )
291
273
return
292
274
}
293
275
@@ -297,15 +279,15 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
297
279
} else {
298
280
putNode , err := i .newDagFromReader (r .Body )
299
281
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 )
301
283
return
302
284
}
303
285
newnode = putNode
304
286
}
305
287
306
288
var newPath string
307
289
if len (rsegs ) > 1 {
308
- newPath = strings .Join (rsegs [2 :], "/" )
290
+ newPath = gopath .Join (rsegs [2 :]... )
309
291
}
310
292
311
293
var newkey key.Key
@@ -317,20 +299,20 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
317
299
// but we need to patch from the root
318
300
rnode , err := i .node .DAG .Get (ctx , key .B58KeyDecode (rsegs [1 ]))
319
301
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 )
321
303
return
322
304
}
323
305
324
306
e := dagutils .NewDagEditor (i .node .DAG , rnode )
325
307
err = e .InsertNodeAtPath (ctx , newPath , newnode , uio .NewEmptyDirectory )
326
308
if err != nil {
327
- webError (w , "putHandler : InsertNodeAtPath failed" , err , http .StatusInternalServerError )
309
+ webError (w , "postHandler : InsertNodeAtPath failed" , err , http .StatusInternalServerError )
328
310
return
329
311
}
330
312
331
313
newkey , err = e .GetNode ().Key ()
332
314
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 )
334
316
return
335
317
}
336
318
@@ -342,11 +324,11 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
342
324
if err != nil {
343
325
nnk , _ := newnode .Key ()
344
326
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 )
346
328
return
347
329
}
348
330
default :
349
- log .Warningf ("putHandler : unhandled resolve error %T" , ev )
331
+ log .Warningf ("postHandler : unhandled resolve error %T" , ev )
350
332
webError (w , "could not resolve root DAG" , ev , http .StatusInternalServerError )
351
333
return
352
334
}
@@ -356,81 +338,56 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
356
338
http .Redirect (w , r , gopath .Join (ipfsPathPrefix , newkey .String (), newPath ), http .StatusCreated )
357
339
}
358
340
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
+ )
376
345
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 )
380
349
return
381
350
}
382
351
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 )
386
353
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 )
388
355
return
389
356
}
390
357
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 )
394
361
return
395
362
}
396
363
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 )
401
366
}
402
367
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 ]))
405
369
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 )
407
371
return
408
372
}
409
373
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 :]... )
418
375
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 )
421
379
return
422
380
}
423
381
424
- // Redirect to new path
425
- key , err := newnode .Key ()
382
+ newkey , err := e .GetNode ().Key ()
426
383
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 )
428
385
return
429
386
}
430
387
431
388
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 )
434
391
}
435
392
436
393
func (i * gatewayHandler ) addUserHeaders (w http.ResponseWriter ) {
@@ -453,8 +410,9 @@ func webError(w http.ResponseWriter, message string, err error, defaultCode int)
453
410
454
411
func webErrorWithCode (w http.ResponseWriter , message string , err error , code int ) {
455
412
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 )
458
416
}
459
417
460
418
// return a 500 error and log
0 commit comments