6
6
"fmt"
7
7
"io"
8
8
"net/http"
9
+ "os"
9
10
gopath "path"
10
11
"runtime/debug"
11
12
"strings"
@@ -20,6 +21,7 @@ import (
20
21
dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
21
22
path "github.com/ipfs/go-ipfs/path"
22
23
ft "github.com/ipfs/go-ipfs/unixfs"
24
+ uio "github.com/ipfs/go-ipfs/unixfs/io"
23
25
24
26
humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
25
27
cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid"
@@ -227,92 +229,102 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
227
229
return
228
230
}
229
231
230
- links , err := i .api .Unixfs (). Ls (ctx , resolvedPath )
232
+ nd , err := i .api .ResolveNode (ctx , resolvedPath )
231
233
if err != nil {
232
234
internalWebError (w , err )
233
235
return
234
236
}
235
237
236
- // storage for directory listing
237
- var dirListing []directoryItem
238
- // loop through files
239
- foundIndex := false
240
- for _ , link := range links {
241
- if link .Name == "index.html" {
242
- log .Debugf ("found index.html link for %s" , urlPath )
243
- foundIndex = true
244
-
245
- if urlPath [len (urlPath )- 1 ] != '/' {
246
- // See comment above where originalUrlPath is declared.
247
- http .Redirect (w , r , originalUrlPath + "/" , 302 )
248
- log .Debugf ("redirect to %s" , originalUrlPath + "/" )
249
- return
250
- }
238
+ dirr , err := uio .NewDirectoryFromNode (i .node .DAG , nd )
239
+ if err != nil {
240
+ internalWebError (w , err )
241
+ return
242
+ }
251
243
252
- dr , err := i .api .Unixfs ().Cat (ctx , coreapi .ParseCid (link .Cid ))
253
- if err != nil {
254
- internalWebError (w , err )
255
- return
256
- }
257
- defer dr .Close ()
244
+ ixnd , err := dirr .Find (ctx , "index.html" )
245
+ switch {
246
+ case err == nil :
247
+ log .Debugf ("found index.html link for %s" , urlPath )
248
+
249
+ if urlPath [len (urlPath )- 1 ] != '/' {
250
+ // See comment above where originalUrlPath is declared.
251
+ http .Redirect (w , r , originalUrlPath + "/" , 302 )
252
+ log .Debugf ("redirect to %s" , originalUrlPath + "/" )
253
+ return
254
+ }
258
255
259
- // write to request
260
- http .ServeContent (w , r , "index.html" , modtime , dr )
261
- break
256
+ dr , err := i .api .Unixfs ().Cat (ctx , coreapi .ParseCid (ixnd .Cid ()))
257
+ if err != nil {
258
+ internalWebError (w , err )
259
+ return
262
260
}
261
+ defer dr .Close ()
263
262
263
+ // write to request
264
+ http .ServeContent (w , r , "index.html" , modtime , dr )
265
+ return
266
+ default :
267
+ internalWebError (w , err )
268
+ return
269
+ case os .IsNotExist (err ):
270
+ }
271
+
272
+ if r .Method == "HEAD" {
273
+ return
274
+ }
275
+
276
+ // storage for directory listing
277
+ var dirListing []directoryItem
278
+ dirr .ForEachLink (ctx , func (link * node.Link ) error {
264
279
// See comment above where originalUrlPath is declared.
265
280
di := directoryItem {humanize .Bytes (link .Size ), link .Name , gopath .Join (originalUrlPath , link .Name )}
266
281
dirListing = append (dirListing , di )
267
- }
282
+ return nil
283
+ })
268
284
269
- if ! foundIndex {
270
- if r .Method != "HEAD" {
271
- // construct the correct back link
272
- // https://github.com/ipfs/go-ipfs/issues/1365
273
- var backLink string = prefix + urlPath
274
-
275
- // don't go further up than /ipfs/$hash/
276
- pathSplit := path .SplitList (backLink )
277
- switch {
278
- // keep backlink
279
- case len (pathSplit ) == 3 : // url: /ipfs/$hash
280
-
281
- // keep backlink
282
- case len (pathSplit ) == 4 && pathSplit [3 ] == "" : // url: /ipfs/$hash/
283
-
284
- // add the correct link depending on wether the path ends with a slash
285
- default :
286
- if strings .HasSuffix (backLink , "/" ) {
287
- backLink += "./.."
288
- } else {
289
- backLink += "/.."
290
- }
291
- }
285
+ // construct the correct back link
286
+ // https://github.com/ipfs/go-ipfs/issues/1365
287
+ var backLink string = prefix + urlPath
292
288
293
- // strip /ipfs/$hash from backlink if IPNSHostnameOption touched the path.
294
- if ipnsHostname {
295
- backLink = prefix + "/"
296
- if len (pathSplit ) > 5 {
297
- // also strip the trailing segment, because it's a backlink
298
- backLinkParts := pathSplit [3 : len (pathSplit )- 2 ]
299
- backLink += path .Join (backLinkParts ) + "/"
300
- }
301
- }
289
+ // don't go further up than /ipfs/$hash/
290
+ pathSplit := path .SplitList (backLink )
291
+ switch {
292
+ // keep backlink
293
+ case len (pathSplit ) == 3 : // url: /ipfs/$hash
302
294
303
- // See comment above where originalUrlPath is declared.
304
- tplData := listingTemplateData {
305
- Listing : dirListing ,
306
- Path : originalUrlPath ,
307
- BackLink : backLink ,
308
- }
309
- err := listingTemplate .Execute (w , tplData )
310
- if err != nil {
311
- internalWebError (w , err )
312
- return
313
- }
295
+ // keep backlink
296
+ case len (pathSplit ) == 4 && pathSplit [3 ] == "" : // url: /ipfs/$hash/
297
+
298
+ // add the correct link depending on wether the path ends with a slash
299
+ default :
300
+ if strings .HasSuffix (backLink , "/" ) {
301
+ backLink += "./.."
302
+ } else {
303
+ backLink += "/.."
314
304
}
315
305
}
306
+
307
+ // strip /ipfs/$hash from backlink if IPNSHostnameOption touched the path.
308
+ if ipnsHostname {
309
+ backLink = prefix + "/"
310
+ if len (pathSplit ) > 5 {
311
+ // also strip the trailing segment, because it's a backlink
312
+ backLinkParts := pathSplit [3 : len (pathSplit )- 2 ]
313
+ backLink += path .Join (backLinkParts ) + "/"
314
+ }
315
+ }
316
+
317
+ // See comment above where originalUrlPath is declared.
318
+ tplData := listingTemplateData {
319
+ Listing : dirListing ,
320
+ Path : originalUrlPath ,
321
+ BackLink : backLink ,
322
+ }
323
+ err = listingTemplate .Execute (w , tplData )
324
+ if err != nil {
325
+ internalWebError (w , err )
326
+ return
327
+ }
316
328
}
317
329
318
330
func (i * gatewayHandler ) postHandler (ctx context.Context , w http.ResponseWriter , r * http.Request ) {
0 commit comments