package httplog import ( // Standard "bytes" "encoding/json" "fmt" "io" "net/http" "os" "time" ) type T struct { logdir string } type HttpMessage struct { Sequence string Timestamp int64 Type string Method string URL string Headers map[string][]string Body string } func NewHttpLog(logdir string) (logger T, err error) { logger.logdir = logdir err = os.MkdirAll(logdir, 0755) return } func (logger T) logMessage(sequence string, messageType, method, url string, headers http.Header, body []byte) (err error) { var message HttpMessage message.Sequence = sequence message.Type = messageType message.Timestamp = time.Now().UnixMilli() message.Method = method message.URL = url message.Body = string(body) message.Headers = make(map[string][]string) for key, val := range headers { message.Headers[key] = val } reqJSON, _ := json.Marshal(message) year, month, day := time.Now().Date() fname := fmt.Sprintf("%s/%s_%04d-%02d-%02d.json", logger.logdir, messageType, year, int(month), day) var logfile *os.File logfile, err = os.OpenFile(fname, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { return } defer logfile.Close() _, err = logfile.Write(reqJSON) if err != nil { return } _, err = logfile.Write([]byte("\n")) return } func (logger T) Request(sequence string, req *http.Request) (err error) { bodyReader, _ := req.GetBody() body, _ := io.ReadAll(bodyReader) err = logger.logMessage(sequence, "request", req.Method, req.URL.String(), req.Header, body) return } func (logger T) Response(sequence string, res *http.Response) (err error) { body, _ := io.ReadAll(res.Body) res.Body.Close() res.Body = io.NopCloser(bytes.NewBuffer(body)) err = logger.logMessage(sequence, "response", res.Request.Method, res.Request.URL.String(), res.Header, body) return }