func LogPanicHandler(l app.Logger) func(w http.ResponseWriter, req *http.Request, p interface{}) { return func(w http.ResponseWriter, req *http.Request, p interface{}) { l.Output(2, fmt.Sprintf("ERROR: panic in HTTP handler - %s", p)) Decorate(func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { return nil, Err{500, "INTERNAL_ERROR"} }, Log(l), V1)(w, req, nil) } }
func Log(l app.Logger) Decorator { return func(f APIHandler) APIHandler { return func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { start := time.Now() response, err := f(w, req, ps) elapsed := time.Since(start) status := 200 if e, ok := err.(Err); ok { status = e.Code } l.Output(2, fmt.Sprintf("%d %s %s (%s) %s", status, req.Method, req.URL.RequestURI(), req.RemoteAddr, elapsed)) return response, err } } }
func Serve(listener net.Listener, handler http.Handler, l app.Logger, proto string) { l.Output(2, fmt.Sprintf("%s: listening on %s", proto, listener.Addr())) server := &http.Server{ Handler: handler, } err := server.Serve(listener) // theres no direct way to detect this error because it is not exposed if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { l.Output(2, fmt.Sprintf("ERROR: http.Serve() - %s", err)) } l.Output(2, fmt.Sprintf("%s: closing %s", proto, listener.Addr())) }
func TCPServer(listener net.Listener, handler TCPHandler, l app.Logger) { l.Output(2, fmt.Sprintf("TCP: listening on %s", listener.Addr())) for { clientConn, err := listener.Accept() if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Temporary() { l.Output(2, fmt.Sprintf("NOTICE: temporary Accept() failure - %s", err)) runtime.Gosched() continue } // theres no direct way to detect this error because it is not exposed if !strings.Contains(err.Error(), "use of closed network connection") { l.Output(2, fmt.Sprintf("ERROR: listener.Accept() - %s", err)) } break } go handler.Handle(clientConn) } l.Output(2, fmt.Sprintf("TCP: closing %s", listener.Addr())) }