{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/21548","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/21548/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/21548/comments","events_url":"https://api.github.com/repos/golang/go/issues/21548/events","html_url":"https://github.com/golang/go/issues/21548","id":251761732,"number":21548,"title":"net/http: Add Error Callbacks","user":{"login":"theory","id":46604,"avatar_url":"https://avatars3.githubusercontent.com/u/46604?v=4","gravatar_id":"","url":"https://api.github.com/users/theory","html_url":"https://github.com/theory","followers_url":"https://api.github.com/users/theory/followers","following_url":"https://api.github.com/users/theory/following{/other_user}","gists_url":"https://api.github.com/users/theory/gists{/gist_id}","starred_url":"https://api.github.com/users/theory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theory/subscriptions","organizations_url":"https://api.github.com/users/theory/orgs","repos_url":"https://api.github.com/users/theory/repos","events_url":"https://api.github.com/users/theory/events{/privacy}","received_events_url":"https://api.github.com/users/theory/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2017-08-21T20:27:06Z","updated_at":"2017-08-23T21:35:33Z","closed_at":null,"body":"I've written a little REST server on net/http that's *supposed* to only ever return JSON contents. At least, that's what the parts I wrote do. However, there are certain errors that net/http encounters before my code is ever called. In those situations, I have no access to any code to determine what the content type and message should be for a given error. For example, take this stupid simple implementation:\r\n\r\n    package main\r\n\r\n    import (\r\n    \t\"encoding/json\"\r\n    \t\"net/http\"\r\n    )\r\n\r\n    type Server struct{}\r\n\r\n    func (server *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {\r\n    \tw.Header().Set(\"Content-Type\", \"application/json; charset=UTF-8\")\r\n    \tw.WriteHeader(http.StatusOK)\r\n    \tif err := json.NewEncoder(w).Encode(http.StatusText(http.StatusOK)); err != nil {\r\n    \t\tpanic(err)\r\n    \t}\r\n    }\r\n\r\n    func main() {\r\n    \thttp.ListenAndServe(\":8080\", &Server{})\r\n    }\r\n\r\nIf I submit a request with borked headers (this one has a wayward newline in the `Authorization` header), my `ServeHTTP()` method is never called, presumably because there's an error when parsing the request to create the Request object:\r\n\r\n    > curl -i -H 'Authorization: Basic hi\r\n    there' 'http://localhost:8080/'\r\n    HTTP/1.1 400 Bad Request\r\n    Content-Type: text/plain; charset=utf-8\r\n    Connection: close\r\n\r\n    400 Bad Request\r\n\r\nThis makes complete sense to me, but if I'm creating an API with a contract to only ever return JSON, I'd like to have some way to plug into this error response and set the content-type and the body. I think the same challenge exists for `Not Found` errors. Perhaps there could be special handlers to configure these situations, similar to how Gorilla mux [provides](http://www.gorillatoolkit.org/pkg/mux#Router) an assignable `NotFoundHandler` field in its Router object?\r\n\r\nI'm not sure exactly what a generalized interface would look like for such error handlers (methods on Handler protocol?), but some way to hook in and get some control over net/http-initiated error responses would be very useful for guaranteeing the content-type contract of a web API."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/324469377","html_url":"https://github.com/golang/go/issues/21548#issuecomment-324469377","issue_url":"https://api.github.com/repos/golang/go/issues/21548","id":324469377,"user":{"login":"ianlancetaylor","id":3194333,"avatar_url":"https://avatars2.githubusercontent.com/u/3194333?v=4","gravatar_id":"","url":"https://api.github.com/users/ianlancetaylor","html_url":"https://github.com/ianlancetaylor","followers_url":"https://api.github.com/users/ianlancetaylor/followers","following_url":"https://api.github.com/users/ianlancetaylor/following{/other_user}","gists_url":"https://api.github.com/users/ianlancetaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/ianlancetaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianlancetaylor/subscriptions","organizations_url":"https://api.github.com/users/ianlancetaylor/orgs","repos_url":"https://api.github.com/users/ianlancetaylor/repos","events_url":"https://api.github.com/users/ianlancetaylor/events{/privacy}","received_events_url":"https://api.github.com/users/ianlancetaylor/received_events","type":"User","site_admin":false},"created_at":"2017-08-23T21:35:33Z","updated_at":"2017-08-23T21:35:33Z","body":"#10123 is closed, so should we close this one as well?  Or with more experience does this seem like a real problem that net/http ought to address?"}}
{"actor":{"display_login":"ianlancetaylor"}}