Eric Bower: 1 Add access and error logging for requests made to the server. 3 files changed, 39 insertions(+), 14 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~gsthnz/public-inbox/patches/20794/mbox | git am -3Learn more about email & git
--- I used nginx as a template for access and error logs. The access logs go to stdout and the error logs go to stdin. ex access logs: 12.123.123.12:58282 [2021-03-06 05:03:38.467249638 +0000 UTC m=+13.910850447] "GET index.gmi" [20] 12.123.123.12:58284 [2021-03-06 05:15:34.430020167 +0000 UTC m=+729.873620943] "GET /sdfsf" [51] ex error logs: 2021-03-06 05:15:34.430449671 +0000 UTC m=+729.874050458 [error] Not found, client: 12.123.123.12:58284, request: "GET /sdfsf" gemini.go | 15 +++++++++------ logging.go | 21 +++++++++++++++++++++ server.go | 17 +++++++++-------- 3 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 logging.go diff --git a/gemini.go b/gemini.go index 4f01574..97f3553 100644 --- a/gemini.go +++ b/gemini.go @@ -36,7 +36,7 @@ func handleRequest(c net.Conn, di int, parsedURL *url.URL) { redirectPermanent(c, parsedURL.String()) return } else if parsedURL.Path != path.Clean(parsedURL.Path) { - sendError(c, BadRequest, "Path error") + sendError(c, BadRequest, "Path error", parsedURL.Path) return } @@ -52,14 +52,14 @@ func serve(c net.Conn, di int, filepath string) { pathInfo, err := os.Stat(fullPath) if err != nil { - sendError(c, NotFound, "Not found") + sendError(c, NotFound, "Not found", filepath) return } if pathInfo.IsDir() { subDirIndex := path.Join(fullPath, IndexFile) if _, err := os.Stat(subDirIndex); os.IsNotExist(err) { - sendError(c, NotFound, "Not found") + sendError(c, NotFound, "Not found", filepath) return } @@ -69,17 +69,18 @@ func serve(c net.Conn, di int, filepath string) { mimeType := getMimeType(fullPath) if mimeType == "" { - sendError(c, NotFound, "") + sendError(c, NotFound, "", filepath) return } file, err := os.Open(fullPath) if err != nil { - sendError(c, NotFound, "") + sendError(c, NotFound, "", filepath) return } defer file.Close() + accessLog(c, Success, filepath) success(c, file, mimeType) } @@ -87,7 +88,9 @@ func redirectPermanent(c net.Conn, url string) { c.Write(getResponseBytes(RedirectPermanent, url)) } -func sendError(c net.Conn, code int, message string) { +func sendError(c net.Conn, code int, message string, url string) { + accessLog(c, code, url) + errorLog(c, url, message) c.Write(getResponseBytes(code, message)) } diff --git a/logging.go b/logging.go new file mode 100644 index 0000000..652bd47 --- /dev/null +++ b/logging.go @@ -0,0 +1,21 @@ +package main + +import ( + "log" + "os" + "net" + "time" +) + +var ( + accessLogger = log.New(os.Stdout, "", 0) + errorLogger = log.New(os.Stderr, "", 0) +) + +func accessLog(c net.Conn, code int, url string) { + accessLogger.Printf("%s [%s] \"GET %s\" [%d]", c.RemoteAddr(), time.Now(), url, code) +} + +func errorLog(c net.Conn, url string, msg string) { + errorLogger.Printf("%s [error] %s, client: %s, request: \"GET %s\"", time.Now(), msg, c.RemoteAddr(), url) +} diff --git a/server.go b/server.go index eacdc16..85410c0 100644 --- a/server.go +++ b/server.go @@ -59,33 +59,34 @@ func handleConnection(c net.Conn) { rawURL := strings.TrimSpace(req) if rawURL == "" { - sendError(c, BadRequest, "Empty URL") + sendError(c, BadRequest, "Empty URL", rawURL) return } else if !utf8.ValidString(rawURL) { - sendError(c, BadRequest, "Non UTF-8 Request") + sendError(c, BadRequest, "Non UTF-8 Request", rawURL) return } else if len(rawURL) > MaxURLSize { - sendError(c, BadRequest, "URL Larger than 1024 bytes") + sendError(c, BadRequest, "URL Larger than 1024 bytes", rawURL) return } parsedURL, err := url.Parse(rawURL) if err != nil { - sendError(c, BadRequest, "Bad URL") + sendError(c, BadRequest, "Bad URL", rawURL) + return } if parsedURL.Scheme == "" { parsedURL.Scheme = "gemini" } if parsedURL.Scheme != "gemini" { - sendError(c, ProxyRequestRefused, fmt.Sprintf("Unknown scheme '%s'", parsedURL.Scheme)) + sendError(c, ProxyRequestRefused, fmt.Sprintf("Unknown scheme '%s'", parsedURL.Scheme), parsedURL.Path) return } else if parsedURL.Host == "" { - sendError(c, BadRequest, "Host not supplied") + sendError(c, BadRequest, "Host not supplied", parsedURL.Path) return } _, port, _ := net.SplitHostPort(c.LocalAddr().String()) if parsedURL.Port() != "" && parsedURL.Port() != port { - sendError(c, ProxyRequestRefused, "Wrong port") + sendError(c, ProxyRequestRefused, "Wrong port", parsedURL.Path) return } @@ -96,5 +97,5 @@ func handleConnection(c net.Conn) { } } sendError(c, ProxyRequestRefused, fmt.Sprintf("Host not found '%s'", - parsedURL.Host)) + parsedURL.Host), parsedURL.Path) } -- 2.30.1
Hi there, thanks for another patch! I have one suggestion. Could you make logging configurable and inactive by default? It should be just the case of adding a "Logging" entry to the Config struct and accepting "off" and "nginx" (Not sure if we use "nginx" or "clf" from Common Logging Format, your choice :p). This would allow us to add more logging templates in the future. I was reading through the gemini mailing list and it doesn't seem to be a consensus if logging is needed/required. So we should keep this as a decision for the server admin. Since keeping logs could be a liability for some. Otherwise this patch looks good! Thanks a lot! -- Gustavo Heinz