From 622dd03bff5a56edc85b029aeb8846778856ce12 Mon Sep 17 00:00:00 2001 From: Minhaz Ahmed Syrus Date: Sat, 27 Oct 2018 18:32:35 +0600 Subject: [PATCH] Initial commit --- .gitignore | 3 ++ README.md | 3 ++ cmd/req-check/main.go | 102 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cmd/req-check/main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1ff94f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +.DS_Store +build diff --git a/README.md b/README.md new file mode 100644 index 0000000..640ccab --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# req-check + +This is a basic go http server for checking and dumping incoming requests diff --git a/cmd/req-check/main.go b/cmd/req-check/main.go new file mode 100644 index 0000000..766cfe3 --- /dev/null +++ b/cmd/req-check/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "encoding/json" + "flag" + "io" + "mime" + "net/http" + "strconv" + "strings" + "time" +) + +// MiB is 1 mega byte +const MiB = 1 << (10 * 2) + +var ( + port, bcap int +) + +func main() { + flag.IntVar(&port, "port", 8080, "server port") + flag.IntVar(&bcap, "cap", 512, "max request body bytes in response") + flag.Parse() + + http.ListenAndServe(":"+strconv.Itoa(port), http.HandlerFunc(HandleReq)) +} + +// HandleReq serves req info +func HandleReq(w http.ResponseWriter, r *http.Request) { + resp := map[string]interface{}{} + resp["time"] = time.Now().UTC().Format(time.RFC3339Nano) + resp["method"] = r.Method + resp["uri"] = r.Host + r.RequestURI + resp["query"] = r.URL.Query() + resp["headers"] = r.Header + resp["remote_addr"] = r.RemoteAddr + + defer r.Body.Close() + body, cpd, err := parseBody(r) + if err != nil { + resp["body_error"] = err.Error() + } + resp["body_capped"] = cpd + resp["body"] = body + if body != nil { + if data, ok := body.([]byte); ok { + typ := http.DetectContentType(data) + if strings.HasPrefix(typ, "text/") { + resp["body"] = string(data) + } + resp["body_context_type"] = typ + } + } + + w.Header().Set("Content-Type", mime.TypeByExtension(".json")) + w.WriteHeader(200) + + json.NewEncoder(w).Encode(resp) +} + +func parseBody(r *http.Request) (interface{}, bool, error) { + typ, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return nil, false, err + } + + switch typ { + case "application/json": + body := map[string]interface{}{} + if err = json.NewDecoder(r.Body).Decode(body); err != nil { + return nil, false, err + } + + case "application/x-www-form-urlencoded": + if err = r.ParseForm(); err != nil { + return nil, false, err + } + return r.PostForm, false, nil + + case "multipart/form-data": + if err = r.ParseMultipartForm(2 * MiB); err != nil { + return nil, false, err + } + return r.MultipartForm, false, nil + } + + body := make([]byte, bcap+1) + capped := false + n, err := r.Body.Read(body) + if err != nil && err != io.EOF { + return nil, false, err + } + body = body[:n] + + if len(body) > bcap { + capped = true + body = body[:bcap] + } + + return body, capped, nil +}