diff --git a/handler.go b/handler.go index 171cde1..2a9b354 100644 --- a/handler.go +++ b/handler.go @@ -5,19 +5,30 @@ import ( "fmt" "net" "net/url" + "time" ) -func handleGeminiRequest(conn net.Conn, config Config) { +func handleGeminiRequest(conn net.Conn, config Config, logEntries chan LogEntry) { defer conn.Close() + var log LogEntry + log.Time = time.Now() + log.RemoteAddr = conn.RemoteAddr() + log.RequestURL = "-" + log.Status = 0 + // Read request reader := bufio.NewReaderSize(conn, 1024) request, overflow, err := reader.ReadLine() if overflow { conn.Write([]byte("59 Request too long!r\n")) + log.Status = 59 + logEntries <- log return } else if err != nil { conn.Write([]byte("40 Unknown error reading request!r\n")) + log.Status = 40 + logEntries <- log return } @@ -25,11 +36,15 @@ func handleGeminiRequest(conn net.Conn, config Config) { URL, err := url.Parse(string(request)) if err != nil { conn.Write([]byte("59 Error parsing URL!r\n")) + log.Status = 59 + logEntries <- log return } - + log.RequestURL = URL.String() // Generic response conn.Write([]byte("20 text/gemini\r\n")) body := fmt.Sprintf("Molly at %s says \"Hi!\" from %s.\n", URL.Host, URL.Path) conn.Write([]byte(body)) + log.Status = 20 + logEntries <- log } diff --git a/logging.go b/logging.go new file mode 100644 index 0000000..afeb2e2 --- /dev/null +++ b/logging.go @@ -0,0 +1,25 @@ +package main + +import ( + "net" + "os" + "strconv" + "time" +) + +type LogEntry struct { + Time time.Time + RemoteAddr net.Addr + RequestURL string + Status int +} + +func writeLogEntry(fp *os.File, entry LogEntry) { + var line string + line = "[" + entry.Time.Format(time.UnixDate)+ "]" + line += "\t" + strconv.Itoa(entry.Status) + line += "\t" + entry.RemoteAddr.String() + line += "\t" + entry.RequestURL + line += "\n" + fp.WriteString(line) +} diff --git a/main.go b/main.go index 67e8fb3..f2e296d 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,14 @@ func main() { os.Exit(1) } + // Open logfile + logfile, err := os.OpenFile(config.LogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + fmt.Println("Error opening log file " + config.LogPath + ".") + os.Exit(2) + } + defer logfile.Close() + // Read TLS files, create TLS config cert, err := tls.LoadX509KeyPair(config.CertPath, config.KeyPath) if err != nil { @@ -44,13 +52,22 @@ func main() { } defer listener.Close() + // Start log handling routine + logEntries := make(chan LogEntry, 10) + go func () { + for { + entry := <- logEntries + writeLogEntry(logfile, entry) + } + }() + // Infinite serve loop for { conn, err := listener.Accept() if err != nil { log.Fatal(err) } - go handleGeminiRequest(conn, config) + go handleGeminiRequest(conn, config, logEntries) } }