I want to set Content-Type (and Content-Length) for HEAD request. That is not done correctly in the standard library!
The only thing I find confusing is that the Set(key, value string) doesn't override the Content-Type header if it already exists. The API documentation says exactly this.
On Fri, Dec 14, 2012 at 2:47 PM, Christian <chri...@helmbold.de> wrote:I want to set Content-Type (and Content-Length) for HEAD request. That is not done correctly in the standard library!please elaborate on this?
if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" { w.needSniff = true }
This indicates that the content type should not be detected on HEAD requests. If I think about it, this may be correct in general, because a handler would typically not send a body as an answer to a HEAD request. In my case I generate a HEAD handler automatically if there is a GET handler.
i think it's the http handlers' job to handle HEAD requests (i.e they should set Content-Length/Content-Type directly,and shouldn't write to the ResponseWriter).
The only thing I find confusing is that the Set(key, value string) doesn't override the Content-Type header if it already exists. The API documentation says exactly this.Set will override an existing entry.I think the problem is that you can't modify the header once it's already been sent out.
--
Am Freitag, 14. Dezember 2012 07:51:35 UTC+1 schrieb minux:On Fri, Dec 14, 2012 at 2:47 PM, Christian <chri...@helmbold.de> wrote:
I want to set Content-Type (and Content-Length) for HEAD request. That is not done correctly in the standard library!please elaborate on this?
The mistake is in this check:
if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" { w.needSniff = true }
This indicates that the content type should not be detected on HEAD requests. If I think about it, this may be correct in general, because a handler would typically not send a body as an answer to a HEAD request. In my case I generate a HEAD handler automatically if there is a GET handler.
--
This doesn't make sense. Once you start writing a body you cannot
change the header, which must be written to the network before the
body.
After all these explanations and some subtle things I think, that it was a bad idea to create autmatic HEAD handling by discarding the body of a GET response. If someone wants to support GET he should go the extra mile an do it properly.
--
Many services, e.g. link services like URL shorteners or social networks (to validate a link) assume you support HEAD. Any net/http handler supports it seamlessly. Very few people actually need to create a custom HEAD handler compared to how many things would break if it were explicit.
On Sat, Dec 15, 2012 at 1:15 PM, Christian <chri...@helmbold.de> wrote:
After all these explanations and some subtle things I think, that it was a bad idea to create autmatic HEAD handling by discarding the body of a GET response. If someone wants to support GET he should go the extra mile an do it properly.
Do you mean go the extra mile and support HEAD? It'd be a pretty odd service to support GET but not head (the meta is the resource?)
--
Yeah, that's a natural side effect of the language being imperative/procedural. Declarative-style web servers have been done, especially in python, where you have methods called 'do_GET' and 'do_HEAD' as part of a handler class. The downside of those is that you have to go out of your way to do any common request handling (for example, using the same code to handle the common bits between a HEAD and GET request to the same resource).http.ServeContent should be suitable for common handling of GET and HEAD (though this is an opt-in mechanism, not an opt-out, as would be involved with a discarding writer); ServeContent is smart enough to handle range requests and a great deal of the "trickier" http stuff that usually goes unimplemented in apps. If you have a dynamic data resource (such as providing a number of line-separated random numbers based on query parameters), the trick is to not necessarily "push" that data to the writer, but to (also) provide it as an io.ReadSeeker where possible, in which case you can let ServeContent do all the protocol work for you. If it's a HEAD request, ServeContent will only seek to the end (to find the Content-Length), try to let the client use a cached copy if fresh, and sniff the first 1024 bytes if the Content-Type header isn't already set. An io.ReadSeeker that generates its content on the fly could easily special-
Note that most of these languages/frameworks use some kind of inheritance, such that do_HEAD by default simply does do_GET but avoids sending a body, and can be overridden by the programmer. That is exactly what Go provides. If you are worried about HEAD performance, you write your own HEAD handler. It is much less important, generally, than actually supporting HEAD.