fix: format of date when MR was closed or merged (#367) refactor: Add Payload Validators + Middleware In Go Code (#366) fix: Add better checks for leaving comments (#369) fix: regex support for http credentials embedded in remote url (#372) fix: Comment on single line selects two lines (#371) This is a #PATCH release.
97 lines
2.5 KiB
Go
97 lines
2.5 KiB
Go
package app
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"os"
|
|
)
|
|
|
|
// LoggingServer is a wrapper around an http.Handler to log incoming requests and outgoing responses.
|
|
type LoggingServer struct {
|
|
handler http.Handler
|
|
}
|
|
|
|
type LoggingResponseWriter struct {
|
|
statusCode int
|
|
body *bytes.Buffer
|
|
http.ResponseWriter
|
|
}
|
|
|
|
func (l *LoggingResponseWriter) WriteHeader(statusCode int) {
|
|
l.statusCode = statusCode
|
|
}
|
|
|
|
func (l *LoggingResponseWriter) Write(b []byte) (int, error) {
|
|
l.body.Write(b)
|
|
return l.ResponseWriter.Write(b)
|
|
}
|
|
|
|
// Logs the request, calls the original handler on the ServeMux, then logs the response
|
|
func (l LoggingServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if pluginOptions.Debug.Request {
|
|
logRequest("REQUEST TO GO SERVER", r)
|
|
}
|
|
lrw := &LoggingResponseWriter{ResponseWriter: w, body: &bytes.Buffer{}}
|
|
l.handler.ServeHTTP(lrw, r)
|
|
resp := &http.Response{
|
|
Status: http.StatusText(lrw.statusCode),
|
|
StatusCode: lrw.statusCode,
|
|
Body: io.NopCloser(bytes.NewBuffer(lrw.body.Bytes())), // Use the captured body
|
|
ContentLength: int64(lrw.body.Len()),
|
|
Header: lrw.Header(),
|
|
Request: r,
|
|
}
|
|
if pluginOptions.Debug.Response {
|
|
logResponse("RESPONSE FROM GO SERVER", resp)
|
|
}
|
|
}
|
|
|
|
func logRequest(prefix string, r *http.Request) {
|
|
file := openLogFile()
|
|
defer file.Close()
|
|
token := r.Header.Get("Private-Token")
|
|
r.Header.Set("Private-Token", "REDACTED")
|
|
res, err := httputil.DumpRequest(r, true)
|
|
if err != nil {
|
|
log.Fatalf("Error dumping request: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
r.Header.Set("Private-Token", token)
|
|
_, err = file.Write([]byte(fmt.Sprintf("\n-- %s --\n%s\n", prefix, res))) //nolint:all
|
|
}
|
|
|
|
func logResponse(prefix string, r *http.Response) {
|
|
file := openLogFile()
|
|
defer file.Close()
|
|
|
|
res, err := httputil.DumpResponse(r, true)
|
|
if err != nil {
|
|
log.Fatalf("Error dumping response: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
_, err = file.Write([]byte(fmt.Sprintf("\n-- %s --\n%s\n", prefix, res))) //nolint:all
|
|
}
|
|
|
|
func openLogFile() *os.File {
|
|
file, err := os.OpenFile(pluginOptions.LogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
log.Printf("Log file %s does not exist", pluginOptions.LogPath)
|
|
} else if os.IsPermission(err) {
|
|
log.Printf("Permission denied for log file %s", pluginOptions.LogPath)
|
|
} else {
|
|
log.Printf("Error opening log file %s: %v", pluginOptions.LogPath, err)
|
|
}
|
|
|
|
os.Exit(1)
|
|
}
|
|
|
|
return file
|
|
}
|