I have a webserver written in go and I'm serving some audio files from different sources (local, other servers, S3). I want to enable serving partial content for this files so the HTML audio tags are able to seek and loop.
How can I achive this? I know that the http
package ServeContent
function does this but how can I do it by serving the files myself? I need to do it without this so that I can serve files from different sources with the same handler.
Serving partial content is non-trivial. See Byte serving on wikipedia for an introduction. You have to handle specific status codes and headers (both request and response), which is not too hard but you shouldn't waste your time doing that yourself.
If the content to serve (or serve from) is a file, you may use
http.ServeFile()
just as you mentioned, which handles serving partial content (Range requests).If the content to be served is not present as a file, then
http.ServeContent()
is your friend:And yes, it also handles serving partial content (Range requests):
All you need to do is provide an
io.ReadSeeker
"view" of your content, this is required so that the implementation can "jump" to the part that is requested by the client, the part that needs to be served. You might ask: how to do that?The
bytes
package contains a type that implementsio.ReadSeeker
:bytes.Reader
.So for example if you have the content as a
[]byte
, you may obtain anio.ReadSeeker
like this:And what if you don't have the whole content as a
[]byte
? One option is to provide a value of your own type that implementsio.ReadSeeker
.io.ReadSeeker
is:io.Reader
contains one method:io.Seeker
also contains one method:Your content is accessible somewhere, somehow, you know how.
Seek()
is called to let you know what part (position) is required from your content, andRead()
is called so you can populate the passed slice (to provide the actual content). Note that these methods may be called multiple times, so you have to keep track where you are in your content (source). If you choose to go down this path, please read the doc of the linked interfaces to make sure you meet the "general contract" of the interfaces to avoid surprise errors.