Skip to content

Commit

Permalink
improve logging, add X-Forwarded-User header
Browse files Browse the repository at this point in the history
  • Loading branch information
mazzz1y committed Jun 15, 2023
1 parent 4807320 commit 5b146cf
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 30 deletions.
8 changes: 2 additions & 6 deletions cmd/go-matrix-webhook/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"net/http"

"github.com/gorilla/mux"
"github.com/mazzz1y/go-matrix-webhook/internal/handler"
"github.com/mazzz1y/go-matrix-webhook/internal/matrix"
"github.com/rs/zerolog/log"
Expand All @@ -28,12 +27,9 @@ func run(c *cli.Context) error {
if err != nil {
panic(err)
}
h := handler.NewHandler(*m, secretHeader)

router := mux.NewRouter().StrictSlash(true)
router.HandleFunc(listenPath, h).Methods("POST")
http.HandleFunc(listenPath, handler.NewHandler(*m, secretHeader))

listen := fmt.Sprintf("%s:%d", listenAddr, listenPort)
log.Info().Err(err).Msgf("listen on: %s", listen)
return http.ListenAndServe(listen, router)
return http.ListenAndServe(listen, nil)
}
7 changes: 3 additions & 4 deletions cmd/go-matrix-webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ func main() {
Value: "/",
},
&cli.StringFlag{
Name: "secret-header",
Usage: "secret header",
EnvVars: []string{"SECRET_HEADER"},
Required: true,
Name: "secret-header",
Usage: "secret header",
EnvVars: []string{"SECRET_HEADER"},
},
&cli.StringFlag{
Name: "matrix-access-token",
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/mazzz1y/go-matrix-webhook
go 1.20

require (
github.com/gorilla/mux v1.8.0
github.com/rs/zerolog v1.29.1
github.com/urfave/cli/v2 v2.25.1
maunium.net/go/mautrix v0.15.1
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
Expand Down
73 changes: 56 additions & 17 deletions internal/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package handler
import (
"encoding/json"
"errors"
"io"
"net"
"net/http"
"strings"

"github.com/mazzz1y/go-matrix-webhook/internal/matrix"
"github.com/rs/zerolog/log"
zerolog "github.com/rs/zerolog/log"
)

type WebhookPayload struct {
Expand All @@ -19,54 +22,90 @@ type ResponseData struct {
Message string `json:"message"`
}

func NewHandler(m matrix.Matrix, s string) func(http.ResponseWriter, *http.Request) {
const (
successSent = "message sent"
errInvalidSecret = "invalid secret header"
errParseBodyError = "parse body error"
errJoinRoomError = "join room error"
errSendMessageError = "send message error"
errEmptyMessage = "empty message"
)

func NewHandler(m matrix.Matrix, secret string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("X-Secret") != s {
response(w, http.StatusBadRequest, "invalid secret header")
secretHeader := r.Header.Get("X-Secret")
userHeader := r.Header.Get("X-Forwarded-User")
reqIP := getIP(r)

if secret != "" && secretHeader != secret {
sendResponse(w, http.StatusBadRequest, errInvalidSecret)
return
}

payload, err := parsePayload(r)
log := zerolog.With().Str("ip", reqIP).Str("path", r.URL.Path).Logger()
if userHeader != "" {
log = log.With().Str("user", userHeader).Logger()
}

payload, err := parsePayload(r.Body)
if err != nil {
log.Error().Err(err).Msg("")
response(w, http.StatusBadRequest, "parse body error")
log.Error().Err(err).Msg(errParseBodyError)
sendResponse(w, http.StatusBadRequest, errParseBodyError)
return
}

err = m.JoinRoom(payload.RoomID)
if err != nil {
log.Error().Str("room_id", payload.RoomID).Err(err).Msg("")
response(w, http.StatusInternalServerError, "join room error")
log.Error().Str("room_id", payload.RoomID).Err(err).Msg(errJoinRoomError)
sendResponse(w, http.StatusInternalServerError, errJoinRoomError)
return
}

err = m.SendMessage(payload.RoomID, payload.Message)
if err != nil {
log.Error().Str("room_id", payload.RoomID).Err(err).Msg("")
response(w, http.StatusOK, "send message error")
log.Error().Str("room_id", payload.RoomID).Err(err).Msg(errSendMessageError)
sendResponse(w, http.StatusOK, errSendMessageError)
return
}

log.Debug().Str("room_id", payload.RoomID).Msg("message sent")
response(w, http.StatusOK, "")
log.Debug().Str("room_id", payload.RoomID).Msg(successSent)
sendResponse(w, http.StatusOK, "")
}
}

func parsePayload(r *http.Request) (*WebhookPayload, error) {
func parsePayload(body io.ReadCloser) (*WebhookPayload, error) {
var payload WebhookPayload
err := json.NewDecoder(r.Body).Decode(&payload)
err := json.NewDecoder(body).Decode(&payload)
if err != nil {
return nil, err
}

if payload.Message == "" {
return nil, errors.New("empty message")
return nil, errors.New(errEmptyMessage)
}

return &payload, nil
}

func response(w http.ResponseWriter, code int, msg string) {
func getIP(r *http.Request) string {
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
ipParts := strings.Split(xff, ",")
return strings.TrimSpace(ipParts[0])
}

if xri := r.Header.Get("X-Real-IP"); xri != "" {
return xri
}

if cf := r.Header.Get("CF-Connecting-IP"); cf != "" {
return cf
}

ip, _, _ := net.SplitHostPort(r.RemoteAddr)
return ip
}

func sendResponse(w http.ResponseWriter, code int, msg string) {
if msg == "" {
msg = http.StatusText(code)
}
Expand Down

0 comments on commit 5b146cf

Please sign in to comment.