Description
What version of Go are you using (go version
)?
$ go version go version go1.14.2 darwin/amd64
Does this issue reproduce with the latest release?
Yes.
Description of the issue
The current http server implementation makes it very cumbersome to access TLS handshake errors. I would like to be able to see them in order to add metrics and alerting to my service. (A recent misconfiguration caused all connections to fail, and we were unable to alert on these kinds of errors.)
Today, TLS handshake errors are reported by logging to the http.Server
ErrorLog
logger, if it is set. (Otherwise it goes to the standard logger.)
The line in question:
Line 1798 in 9b18968
c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
And the implementation of logf
:
Lines 3062 to 3080 in 9b18968
func (s *Server) logf(format string, args ...interface{}) {
if s.ErrorLog != nil {
s.ErrorLog.Printf(format, args...)
} else {
log.Printf(format, args...)
}
}
ErrorLog
is a *log.Logger
, which is a struct and not an interface. It wraps an io.Writer
. So in order to capture TLS handshake errors, one must write an io.Writer
wrapper that searches for the string TLS handshake error
. I think (but am not sure) that error messages are not covered by the Go 1 compatibility guarantee, so this method is both ugly and fragile.
It would be nice if there were another way to get notified of TLS handshake errors. This could be implemented as an optional callback function on the http.Server
or tls.Config
structs, or as a channel on http.Server
. It may make sense to generalize it to more HTTP server errors, but we could start with handshake errors.
Reproducing the issue
An easy way to illustrate this in action is to start up a TLS HTTP server (http.ListenAndServeTLS
) and then run nc localhost 1234 </dev/null
. On the server you'll get a log line like 2020/05/05 11:41:59 http: TLS handshake error from 127.0.0.1:63162: EOF