diff --git a/bittorrent/params.go b/bittorrent/params.go index a24d3f6..4e28b73 100644 --- a/bittorrent/params.go +++ b/bittorrent/params.go @@ -5,6 +5,8 @@ import ( "net/url" "strconv" "strings" + + log "github.com/Sirupsen/logrus" ) // Params is used to fetch (optional) request parameters from an Announce. @@ -39,6 +41,10 @@ var ErrKeyNotFound = errors.New("query: value for the provided key does not exis // with invalid length. var ErrInvalidInfohash = ClientError("provided invalid infohash") +// ErrInvalidQueryEscape is returned when a query string contains invalid +// escapes. +var ErrInvalidQueryEscape = ClientError("invalid query escape") + // QueryParams parses a URL Query and implements the Params interface with some // additional helpers. type QueryParams struct { @@ -113,11 +119,21 @@ func parseQuery(query string) (q *QueryParams, err error) { } key, err = url.QueryUnescape(key) if err != nil { - return nil, err + // QueryUnescape returns an error like "invalid escape: '%x'". + // But frontends record these errors to prometheus, which generates + // a lot of time series. + // We log it here for debugging instead. + log.WithFields(log.Fields{"error": err}).Debug("failed to unescape query param key") + return nil, ErrInvalidQueryEscape } value, err = url.QueryUnescape(value) if err != nil { - return nil, err + // QueryUnescape returns an error like "invalid escape: '%x'". + // But frontends record these errors to prometheus, which generates + // a lot of time series. + // We log it here for debugging instead. + log.WithFields(log.Fields{"error": err}).Debug("failed to unescape query param value") + return nil, ErrInvalidQueryEscape } if key == "info_hash" {