From 16a45be28ef0830e0ece60fe4e6e29c5c26e62e9 Mon Sep 17 00:00:00 2001 From: Jon Roeber Date: Wed, 30 Nov 2022 22:46:48 -0500 Subject: [PATCH] initial commit --- .gitignore | 1 + Dockerfile | 18 +++++++++++++++++ LICENSE | 13 +++++++++++++ README.md | 33 +++++++++++++++++++++++++++++++ go.mod | 3 +++ main.go | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4cbf9b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +requests.log \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..626721c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM docker.io/golang:1.19-alpine AS builder + +WORKDIR /app + +COPY go.mod ./ +#COPY go.sum ./ +RUN go mod download + +COPY *.go ./ + +RUN go build -o /reqlog + +FROM alpine:3.17.0 +WORKDIR / +COPY --from=builder /reqlog . + +EXPOSE 3000 +CMD [ "/reqlog" ] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..29e1834 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2022 Jon Roeber + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f0d8ac --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Request Logger + +Serves an HTTP server on port 3000 and logs any requests to a file, stdout, and the response body. + +*This is not intended for production use. It is just a simple diagnostic tool for short-term testing.* + +## General use + +1. Install Docker: `sudo apt install docker.io` +2. Create an empty log file: `touch requests.log` +3. Run a container: + +```bash +docker run \ + --name reqlog \ + --restart always \ + -d \ + -p 3000:3000 \ + -v $(pwd)/requests.log:/requests.log \ + git.roeber.dev/jon/reqlog:v0.0.1 +``` + +4. Test: + +```bash +curl \ + -X POST \ + http://localhost:3000/ \ + -H "Content-Type: application/json" \ + -d '{"temp": 98.6}' +``` + +The request gets logged to `requests.log`, printed to stdout (if running a container in daemon mode, check stdout with `docker logs reqlog`), and returned in the response body. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2668a12 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.roeber.dev/jon/reqlog + +go 1.18 diff --git a/main.go b/main.go new file mode 100644 index 0000000..3626061 --- /dev/null +++ b/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + "net/http/httputil" + "os" + "strings" + "time" +) + +var logFile *string + +func main() { + logFile = flag.String("logfile", "requests.log", "the file to log requests to") + flag.Parse() + + http.HandleFunc("/", post) + err := http.ListenAndServe(":3000", nil) + if err != nil { + panic(err) + } +} + +func post(w http.ResponseWriter, r *http.Request) { + reqDump, err := httputil.DumpRequest(r, true) + if err != nil { + w.WriteHeader(500) + w.Write([]byte(err.Error())) + return + } + // log to stdout + fmt.Print(logString(reqDump)) + + // log to logfile + lf, err := os.OpenFile(*logFile, os.O_CREATE | os.O_APPEND | os.O_WRONLY, 0644) + if err != nil { + fmt.Printf("failed to open log file: %v", err) + w.WriteHeader(500) + w.Write([]byte(fmt.Sprintf("failed to open log file: %v", err))) + } + defer lf.Close() + lf.WriteString(logString(reqDump)) + + // echo log message as response + w.WriteHeader(200) + w.Write([]byte(logString(reqDump))) +} + +func logString(reqDump []byte) string { + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Received request at %v:\n\n", time.Now())) + sb.Write(reqDump) + sb.WriteString("\n\n") + return sb.String() +} \ No newline at end of file