Skip to content

Instantly share code, notes, and snippets.

@reline
Created March 10, 2018 23:48
Show Gist options
  • Save reline/26f903a991c2c1ea1bcfcc3465ea6159 to your computer and use it in GitHub Desktop.
Save reline/26f903a991c2c1ea1bcfcc3465ea6159 to your computer and use it in GitHub Desktop.
Go server
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
)
const DateLogFormat = "2006-01-02 15:04:05.000 -07:00"
func main() {
log.SetFlags(0)
log.SetOutput(new(logger))
server := provideServer()
log.Printf("Listening on %s...\n", server.Addr)
log.Fatal(server.ListenAndServe())
}
type logger struct{}
func (writer logger) Write(bytes []byte) (int, error) {
return fmt.Print(time.Now().Format(DateLogFormat) + " " + string(bytes))
}
type loggingResponseWriter struct {
http.ResponseWriter
statusCode int
}
func NewLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter {
return &loggingResponseWriter{w, http.StatusOK}
}
func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.statusCode = code
lrw.ResponseWriter.WriteHeader(code)
}
type Handler func(http.ResponseWriter, *http.Request) error
type AuthenticationHandler func(http.ResponseWriter, *http.Request) error
// intercept takes an authentication handler and a custom http handler
// and calls them respectively then logs the result.
// This function does not and should not mutate the response writer whatsoever
func intercept(handle Handler, authenticate AuthenticationHandler) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := rand.Int()
before := time.Now()
b := before.Format(DateLogFormat)
fmt.Printf("%s - %d [%s] \"%s %s %s\" Received Request\n", r.RemoteAddr, id, b, r.Method, r.URL.String(), r.Proto)
lrw := NewLoggingResponseWriter(w)
if err := authenticate(lrw, r); err != nil {
statusCode := lrw.statusCode
a := time.Now().Format(DateLogFormat)
fmt.Printf("%s - %d [%s] \"%s %s %s\" %d %dms Error Response: %s\n", r.RemoteAddr, id, a, r.Method, r.URL.String(), r.Proto, statusCode, time.Since(before), err.Error())
return
}
err := handle(lrw, r)
statusCode := lrw.statusCode
after := time.Now()
a := after.Format(DateLogFormat)
if err != nil {
fmt.Printf("%s - %d [%s] \"%s %s %s\" %d %dms Error Response: %s\n", r.RemoteAddr, id, a, r.Method, r.URL.String(), r.Proto, statusCode, time.Since(before), err.Error())
return
}
fmt.Printf("%s - %d [%s] \"%s %s %s\" %d %dms Responded Successfully\n",
r.RemoteAddr, id, a, r.Method, r.URL.String(), r.Proto, statusCode, time.Since(before))
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment