@@ -289,7 +289,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
289289 }
290290
291291 // write to request
292- http . ServeContent (w , r , "index.html" , modtime , f )
292+ i . serveFile (w , r , "index.html" , modtime , f )
293293 return
294294 case resolver.ErrNoLink :
295295 // no index.html; noop
@@ -306,14 +306,14 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
306306 var dirListing []directoryItem
307307 dirit := dir .Entries ()
308308 for dirit .Next () {
309- // See comment above where originalUrlPath is declared.
310- s , err := dirit .Node ().Size ()
311- if err != nil {
312- internalWebError (w , err )
313- return
309+ size := "?"
310+ if s , err := dirit .Node ().Size (); err == nil {
311+ // Size may not be defined/supported. Continue anyways.
312+ size = humanize .Bytes (uint64 (s ))
314313 }
315314
316- di := directoryItem {humanize .Bytes (uint64 (s )), dirit .Name (), gopath .Join (originalUrlPath , dirit .Name ())}
315+ // See comment above where originalUrlPath is declared.
316+ di := directoryItem {size , dirit .Name (), gopath .Join (originalUrlPath , dirit .Name ())}
317317 dirListing = append (dirListing , di )
318318 }
319319 if dirit .Err () != nil {
@@ -372,48 +372,42 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
372372 }
373373}
374374
375- type sizeReadSeeker interface {
376- Size () (int64 , error )
377-
378- io.ReadSeeker
379- }
380-
381- type sizeSeeker struct {
382- sizeReadSeeker
383- }
384-
385- func (s * sizeSeeker ) Seek (offset int64 , whence int ) (int64 , error ) {
386- if whence == io .SeekEnd && offset == 0 {
387- return s .Size ()
375+ func (i * gatewayHandler ) serveFile (w http.ResponseWriter , req * http.Request , name string , modtime time.Time , file files.File ) {
376+ size , err := file .Size ()
377+ if err != nil {
378+ http .Error (w , "cannot serve files with unknown sizes" , http .StatusBadGateway )
379+ return
388380 }
389381
390- return s .sizeReadSeeker .Seek (offset , whence )
391- }
392-
393- func (i * gatewayHandler ) serveFile (w http.ResponseWriter , req * http.Request , name string , modtime time.Time , content io.ReadSeeker ) {
394- if sp , ok := content .(sizeReadSeeker ); ok {
395- content = & sizeSeeker {
396- sizeReadSeeker : sp ,
397- }
382+ content := & lazySeeker {
383+ size : size ,
384+ reader : file ,
398385 }
399386
400- ctype := mime .TypeByExtension (gopath .Ext (name ))
401- if ctype == "" {
402- buf := make ([]byte , 512 )
403- n , _ := io .ReadFull (content , buf [:])
404- ctype = http .DetectContentType (buf [:n ])
405- _ , err := content .Seek (0 , io .SeekStart )
406- if err != nil {
407- http .Error (w , "seeker can't seek" , http .StatusInternalServerError )
408- return
387+ var ctype string
388+ if _ , isSymlink := file .(* files.Symlink ); isSymlink {
389+ // We should be smarter about resolving symlinks but this is the
390+ // "most correct" we can be without doing that.
391+ ctype = "inode/symlink"
392+ } else {
393+ ctype = mime .TypeByExtension (gopath .Ext (name ))
394+ if ctype == "" {
395+ buf := make ([]byte , 512 )
396+ n , _ := io .ReadFull (content , buf [:])
397+ ctype = http .DetectContentType (buf [:n ])
398+ _ , err := content .Seek (0 , io .SeekStart )
399+ if err != nil {
400+ http .Error (w , "seeker can't seek" , http .StatusInternalServerError )
401+ return
402+ }
403+ }
404+ // Strip the encoding from the HTML Content-Type header and let the
405+ // browser figure it out.
406+ //
407+ // Fixes https://github.com/ipfs/go-ipfs/issues/2203
408+ if strings .HasPrefix (ctype , "text/html;" ) {
409+ ctype = "text/html"
409410 }
410- }
411- // Strip the encoding from the HTML Content-Type header and let the
412- // browser figure it out.
413- //
414- // Fixes https://github.com/ipfs/go-ipfs/issues/2203
415- if strings .HasPrefix (ctype , "text/html;" ) {
416- ctype = "text/html"
417411 }
418412 w .Header ().Set ("Content-Type" , ctype )
419413
0 commit comments