diff --git a/app/limiter.go b/app/limiter.go index 55fa326..1754416 100644 --- a/app/limiter.go +++ b/app/limiter.go @@ -6,7 +6,6 @@ import ( "github.com/rs/zerolog/log" "golang.org/x/time/rate" "net/http" - "strings" "sync" "time" ) @@ -77,7 +76,7 @@ func (rl *RateLimiter) cleanupVisitors() { // with the help of https://www.alexedwards.net/blog/how-to-rate-limit-http-requests, TY! func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ip := rl.guessIp(r) + ip := ipFrom(r) limiter := rl.getVisitor(ip) if limiter.Allow() == false { @@ -89,15 +88,3 @@ func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } - -func (rl *RateLimiter) guessIp(r *http.Request) string { - realIp := r.Header.Get("X-Real-IP") - forwardedFor := r.Header.Get("X-Forwarded-For") - if realIp != "" { // in case of proxy. is IP itself - return realIp - } - if forwardedFor != "" { // in case of proxy. Could be: clientip, proxy1, proxy2, ... - return strings.Split(forwardedFor, ",")[0] - } - return r.RemoteAddr // also contains port, but don't care -} diff --git a/app/logging.go b/app/logging.go index 793fd9b..5ebcfb7 100644 --- a/app/logging.go +++ b/app/logging.go @@ -17,12 +17,14 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) { lrw.ResponseWriter.WriteHeader(code) } +// Logs ip (for those pingback bad boys to put in jail), request url, method, and response status code. func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logWriter := &loggingResponseWriter{w, http.StatusOK} next.ServeHTTP(logWriter, r) log.Info(). Str("url", r.RequestURI). + Str("ip", ipFrom(r)). Str("method", r.Method). Int("status", logWriter.statusCode). Msg("handled") diff --git a/app/pingback/handler.go b/app/pingback/handler.go index ba7b836..e81aee7 100644 --- a/app/pingback/handler.go +++ b/app/pingback/handler.go @@ -6,6 +6,7 @@ import ( "brainbaking.com/go-jamming/common" "brainbaking.com/go-jamming/rest" "encoding/xml" + "fmt" "github.com/rs/zerolog/log" "io/ioutil" "net/http" @@ -15,18 +16,18 @@ func HandlePost(conf *common.Config) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - pingbackError(w, "Unable to read request body", []byte("")) + pingbackError(w, fmt.Errorf("pingback POST: Unable to read body: %v", err)) return } rpc := &XmlRPCMethodCall{} err = xml.Unmarshal(body, rpc) if err != nil { - pingbackError(w, "Unable to unmarshal XMLRPC request body", body) + pingbackError(w, fmt.Errorf("pingback POST: Unable to unmarshal XMLRPC %s: %v", body, err)) return } if !validate(rpc, conf) { - pingbackError(w, "malformed pingback request", body) + pingbackError(w, fmt.Errorf("pingback POST: malformed pingback request: %s", body)) return } @@ -61,7 +62,7 @@ func pingbackSuccess(w http.ResponseWriter) { } // according to the XML-RPC spec, always return a 200, but encode it into the XML. -func pingbackError(w http.ResponseWriter, msg string, body []byte) { +func pingbackError(w http.ResponseWriter, err error) { xml := ` @@ -91,7 +92,7 @@ func pingbackError(w http.ResponseWriter, msg string, body []byte) { ` - log.Error().Str("msg", msg).Str("xml", string(body)).Msg("Pingback receive went wrong") + log.Error().Err(err).Msg("Pingback receive went wrong") w.WriteHeader(200) w.Write([]byte(xml)) } diff --git a/app/pingback/xmlrpc_test.go b/app/pingback/xmlrpc_test.go index 99ad99a..fbf5619 100644 --- a/app/pingback/xmlrpc_test.go +++ b/app/pingback/xmlrpc_test.go @@ -6,6 +6,14 @@ import ( "testing" ) +func TestMarshallXmlSpamFromProductionWithMissingDecoderCharset(t *testing.T) { + xmlString := `pingback.pinghttps://teramassage.com/gwangju/https://brainbaking.com/projects/` + var rpc XmlRPCMethodCall + err := xml.Unmarshal([]byte(xmlString), &rpc) + + assert.EqualError(t, err, `xml: encoding "utf-16" declared but Decoder.CharsetReader is nil`) +} + // See https://www.hixie.ch/specs/pingback/pingback#refsXMLRPC func TestMarshallValidXMLRPC(t *testing.T) { xmlString := ` diff --git a/app/server.go b/app/server.go index 3e7ab5d..e120e74 100644 --- a/app/server.go +++ b/app/server.go @@ -5,6 +5,7 @@ import ( "github.com/MagnusFrater/helmet" "net/http" "strconv" + "strings" "brainbaking.com/go-jamming/common" @@ -28,6 +29,18 @@ func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc { } } +func ipFrom(r *http.Request) string { + realIp := r.Header.Get("X-Real-IP") + forwardedFor := r.Header.Get("X-Forwarded-For") + if realIp != "" { // in case of proxy. is IP itself + return realIp + } + if forwardedFor != "" { // in case of proxy. Could be: clientip, proxy1, proxy2, ... + return strings.Split(forwardedFor, ",")[0] + } + return r.RemoteAddr // also contains port, but don't care +} + func Start() { r := mux.NewRouter() config := common.Configure()