http.ServeContent: Content-Encoding and Content-Length mutually exclusive?

532 views
Skip to first unread message

Maxim Khitrov

unread,
Jul 2, 2015, 1:31:49 PM7/2/15
to golang-nuts
I'm embedding some static files into a Go binary as gzip-compressed
strings to be served over HTTP. I'm trying to figure out the proper
way of using http.ServeContent for this. When the client specifies
"gzip" in Accept-Encoding, all I need to do is set the
"Content-Encoding: gzip" header and send the data without any
additional processing.

I noticed, however, that when Content-Encoding is set,
http.ServeContent doesn't add the Content-Length header, even though
that information is available, and "chunked" Transfer-Encoding is used
instead. Is there a good reason for this? Here's the relevant code:

https://golang.org/src/net/http/fs.go#L249

Vitaly Dyatlov

unread,
Jul 3, 2015, 3:45:06 AM7/3/15
to golan...@googlegroups.com
Have a look at their test: https://golang.org/src/net/http/fs_test.go#L429

For transfers with predefined Content-Encoding Content-Length is not being sent to allow unbuffered output of encoded content to a client (without waiting for full encoding to be done if encoding is being done on the fly).

ServeContent uses chunked transfers so this is an expected behaviour: https://en.wikipedia.org/wiki/Chunked_transfer_encoding

Although, if you serve static files you can set this Content-Length header manually for every file in your handler..

Maxim Khitrov

unread,
Jul 3, 2015, 7:43:03 AM7/3/15
to Vitaly Dyatlov, golang-nuts
That explanation would make sense if ServeContent didn't require a
ReadSeeker with a working Seek to determine the size. You can see on
line 175 that ServeContent returns an error if the size can't be
determined:

https://golang.org/src/net/http/fs.go#L175

Content-Length refers to the size after the encoding, so ServeContent
does not allow you to encode on the fly, which seems like an
unnecessary restriction in itself. I realize that I can set the
Content-Length header myself, but I didn't know if there is some
specific reason why it was left out in the first place when it's
always known by that point.

Vitaly Dyatlov

unread,
Jul 3, 2015, 7:54:38 AM7/3/15
to golan...@googlegroups.com
Agree in this case.. weird behaviour

Maxim Khitrov

unread,
Jul 3, 2015, 12:51:55 PM7/3/15
to golang-nuts
Actually, I take back what I said about setting Content-Length myself,
because then I would also need to handle Range requests, negating the
whole point of ServeContent.

Andy Balholm

unread,
Jul 7, 2015, 12:26:40 PM7/7/15
to Maxim Khitrov, golang-nuts
I vaguely remember something about some clients misinterpreting the content-length header with gzipped content, and thinking it was the length of the uncompressed content instead of the compressed content. The simplest workaround for that is for the server to used chunked encoding instead of setting Content-Length.

Tamás Gulácsi

unread,
Jul 7, 2015, 2:39:11 PM7/7/15
to golan...@googlegroups.com
Firefox accepts uncompressed content-length, chrome does not. So just delete the content-length.
Reply all
Reply to author
Forward
0 new messages