Skip to content

proposal: net/http: basic seek support for io.FS #61791

@oliverpool

Description

@oliverpool

Support for io.FS in net/http was added in 7211694

I have been experimenting lately with serving the content of a tar or a zip file via the http.FS. Supporting Seek completely is the most challenging part (and a bad experience, because it breaks at runtime, on specific files - when the MIME type must be detected).

However after analyzing the code of net/http, it appears that Seek is only called in 2 cases:

  • sniff the MIME ContentType and seek back to the beginning afterward
  • for range requests

Instead of properly implementing Seek I attempted an alternative approach, faking just enough of the Seek method to support:

  • sniff the MIME ContentType and seek at the start afterward (by buffering the first 512 bytes)
  • seek forward for the ranges requests (by discarding the bytes read and failing on non-ascending ranges)

Non-ascending multi-range request will fail on the first request going backward (except if the previous ranges were within sniffLen). And a malicious actor could request the last byte as a range forcing the server to read the whole file (kind of an amplification attack).

I have created an importable package to experiment with this approach:
https://git.sr.ht/~oliverpool/exp/tree/main/item/seekfaker/seekfaker.go

It seems to work (the tests do work at least :), but strongly relies on the internal of net/http (making it quite brittle).

I think it would be a nice addition to the stdlib, to:

  • make it stable
  • improve the integration of io.FS (by reducing drastically the work of io.FS implementers)

The comment added in afd792f could then be reworded to state // The files provided by fsys must implement io.Seeker to efficiently support range requests.

Draft for the changes to the stdlib: https://git.sr.ht/~oliverpool/go/tree/httpfs_seekable/item/src/net/http/fsys.go (adapted from the fs.go file).

2023-08-07: updated wording to address the misunderstanding of #61791 (comment)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions