{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/9424","labels_url":"https://api.github.com/repos/golang/go/issues/9424/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/9424/comments","events_url":"https://api.github.com/repos/golang/go/issues/9424/events","html_url":"https://github.com/golang/go/issues/9424","id":52696459,"number":9424,"title":"net/http: Errors from *Client methods are poorly documented.","user":{"login":"bcmills","id":5200974,"avatar_url":"https://avatars.githubusercontent.com/u/5200974?v=3","gravatar_id":"","url":"https://api.github.com/users/bcmills","html_url":"https://github.com/bcmills","followers_url":"https://api.github.com/users/bcmills/followers","following_url":"https://api.github.com/users/bcmills/following{/other_user}","gists_url":"https://api.github.com/users/bcmills/gists{/gist_id}","starred_url":"https://api.github.com/users/bcmills/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bcmills/subscriptions","organizations_url":"https://api.github.com/users/bcmills/orgs","repos_url":"https://api.github.com/users/bcmills/repos","events_url":"https://api.github.com/users/bcmills/events{/privacy}","received_events_url":"https://api.github.com/users/bcmills/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/golang/go/labels/Go2","name":"Go2","color":"ffaaaa"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/6","html_url":"https://github.com/golang/go/milestones/Unplanned","labels_url":"https://api.github.com/repos/golang/go/milestones/6/labels","id":1055141,"number":6,"title":"Unplanned","description":"No plan to fix in any specific release.\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":889,"closed_issues":50,"state":"open","created_at":"2015-04-06T20:47:19Z","updated_at":"2015-06-25T20:57:30Z","due_on":"2099-12-31T05:00:00Z","closed_at":null},"comments":25,"created_at":"2014-12-22T22:42:31Z","updated_at":"2015-06-25T21:55:45Z","closed_at":null,"body":"I've been doing some experimenting with Go HTTP clients and servers under load.\r\nOne of the curious things I've discovered is that calls to (*http.Client).Get occasionally return unusual errors.\r\n\r\nThe documentation at http://golang.org/pkg/net/http/#Client says:\r\n\"An error is returned if the Client's CheckRedirect function fails or if there was an HTTP protocol error.\"\r\n\r\nI've been leaving CheckRedirect nil and testing against a local server that never serves redirects.  From the comment, that would imply that I should only receive HTTP protocol errors - which would correspond to the type *http.ProtocolError.\r\n\r\nFor typical socket errors, the clients in fact return a *url.Error - but the only place in the net/http documentation where url.Error is even mentioned is for the client.CheckRedirect field, which is completely unrelated to the errors I'm testing.\r\n\r\n\r\nBut that's not all!\r\n\r\nThe *url.Error usually wraps a net.OpError, which seems reasonable enough.  In fact, net.Error is what I would have expected in the first place, since I didn't know about url.Error at all before I started these experiments.\r\n\r\nBut instead, the *url.Error occasionally wraps io.EOF.  I'm guessing that happens when the socket happens to close at exactly the wrong moment, and because of the poor documentation it's not at all clear to me whether that's the intended behavior of the Client methods or an outright bug in the library.\r\n\r\n\r\nBut that's not all either!\r\n\r\nThe error wrapped by the OpError, one would expect, is a net.Error describing the underlying network error for the op.  But that's not the case either - it's often a syscall.Errno instead, and syscall.Errno does not implement net.Error.  So for temporary conditions, such as EPIPE or ECONNRESET, the net package's preferred mechanism for indicating that the condition *is* temporary does not work as expected.\r\n\r\nSo I end up needing a big pile of user code to sort through the whole stack of errors, find the root error, and check for particular syscall.Errno values, and that whole big pile of code is now relying on undocumented error spaces that could theoretically change completely with the next Go release.\r\n\r\n\r\nTo summarize: error handling in the http package is a mess.  Someone familiar with the intended behavior of the package should clarify the documentation at least to the point where it's sensible to say whether the more subtle behaviors (e.g. io.EOF in a url.Error) are bugs or not."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/115410930","html_url":"https://github.com/golang/go/issues/9424#issuecomment-115410930","issue_url":"https://api.github.com/repos/golang/go/issues/9424","id":115410930,"user":{"login":"raphael","id":36822,"avatar_url":"https://avatars.githubusercontent.com/u/36822?v=3","gravatar_id":"","url":"https://api.github.com/users/raphael","html_url":"https://github.com/raphael","followers_url":"https://api.github.com/users/raphael/followers","following_url":"https://api.github.com/users/raphael/following{/other_user}","gists_url":"https://api.github.com/users/raphael/gists{/gist_id}","starred_url":"https://api.github.com/users/raphael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raphael/subscriptions","organizations_url":"https://api.github.com/users/raphael/orgs","repos_url":"https://api.github.com/users/raphael/repos","events_url":"https://api.github.com/users/raphael/events{/privacy}","received_events_url":"https://api.github.com/users/raphael/received_events","type":"User","site_admin":false},"created_at":"2015-06-25T21:55:45Z","updated_at":"2015-06-25T21:55:45Z","body":"@bcmills I would be very interested in seeing the code you came up with to decode the possible errors. Is that available somewhere? (I know it was 6 months ago)."}}