Skip to content

Instantly share code, notes, and snippets.

@fyxme
Last active November 7, 2024 20:07
Show Gist options
  • Save fyxme/835253b1cf247c723008acdc39c67337 to your computer and use it in GitHub Desktop.
Save fyxme/835253b1cf247c723008acdc39c67337 to your computer and use it in GitHub Desktop.
Golang webserver with ip and request logging
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"flag"
"strings"
"os"
)
func main() {
var httpPort int
var serverDir string
var verbose bool
flag.IntVar(&httpPort, "p", 80, "port to listen on")
flag.StringVar(&serverDir, "d", "web", "Directory to serve files from")
flag.BoolVar(&verbose, "v", false, "Verbose mode")
flag.Parse()
if _, err := os.Stat(serverDir); os.IsNotExist(err) {
log.Fatalf("Diretory %v does not exists",serverDir)
}
log.SetOutput(os.Stdout)
http.Handle("/", http.FileServer(http.Dir(serverDir)))
log.Println("Verbose enabled?", verbose)
log.Println("Logging to Stdout. If you need file logs, tee the output (ie. './webserver | tee -a server.log')")
log.Println("Alternatively, log full output to log file and only minimal output to stdout: ./webserver -p 9999 -v | tee server.log | grep \"^2023\" --line-buffered | egrep -v \"Request Dump\"")
log.Printf("Listening on %v and serving from the %v folder\n", httpPort, serverDir)
err := http.ListenAndServe(fmt.Sprintf(":%d", httpPort), logRequest(http.DefaultServeMux, verbose))
if err != nil {
log.Fatal(err)
}
}
func logRequest(handler http.Handler, verbose bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ipAddress := r.RemoteAddr
fwdAddress := r.Header.Get("X-Forwarded-For") // capitalisation doesn't matter
if fwdAddress != "" {
// Got X-Forwarded-For
ipAddress = fwdAddress // If it's a single IP, then awesome!
// If we got an array... grab the first IP
ips := strings.Split(fwdAddress, ", ")
if len(ips) > 1 {
ipAddress = ips[0]
}
}
log.Printf("%s %s %s %s\n", ipAddress, r.RemoteAddr, r.Method, r.URL)
if verbose {
// change to true if you want the Request body as well
dump, err := httputil.DumpRequest(r, false)
if err != nil {
log.Println("Error while dumping above request", err)
} else {
log.Printf("Request Dump:\n%s\n",dump)
}
}
handler.ServeHTTP(w, r)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment