Skip to content

Commit 7c22785

Browse files
committed
prometheus: fix invalid utf8 paths
1 parent 4926816 commit 7c22785

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

echoprometheus/prometheus.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"net/http"
2222
"sort"
2323
"strconv"
24+
"strings"
2425
"time"
2526
)
2627

@@ -271,15 +272,30 @@ func (conf MiddlewareConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
271272
values[0] = strconv.Itoa(status)
272273
values[1] = c.Request().Method
273274
values[2] = c.Request().Host
274-
values[3] = url
275+
values[3] = strings.ToValidUTF8(url, "\uFFFD") // \uFFFD is � https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character
275276
for _, cv := range customValuers {
276277
values[cv.index] = cv.valueFunc(c, err)
277278
}
278-
279-
requestDuration.WithLabelValues(values...).Observe(elapsed)
280-
requestCount.WithLabelValues(values...).Inc()
281-
requestSize.WithLabelValues(values...).Observe(float64(reqSz))
282-
responseSize.WithLabelValues(values...).Observe(float64(c.Response().Size))
279+
if obs, err := requestDuration.GetMetricWithLabelValues(values...); err == nil {
280+
obs.Observe(elapsed)
281+
} else {
282+
return fmt.Errorf("failed to label request duration metric with values, err: %w", err)
283+
}
284+
if obs, err := requestCount.GetMetricWithLabelValues(values...); err == nil {
285+
obs.Inc()
286+
} else {
287+
return fmt.Errorf("failed to label request count metric with values, err: %w", err)
288+
}
289+
if obs, err := requestSize.GetMetricWithLabelValues(values...); err == nil {
290+
obs.Observe(float64(reqSz))
291+
} else {
292+
return fmt.Errorf("failed to label request size metric with values, err: %w", err)
293+
}
294+
if obs, err := responseSize.GetMetricWithLabelValues(values...); err == nil {
295+
obs.Observe(float64(c.Response().Size))
296+
} else {
297+
return fmt.Errorf("failed to label response size metric with values, err: %w", err)
298+
}
283299

284300
return err
285301
}

echoprometheus/prometheus_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,21 @@ func TestSetPathFor404Logic(t *testing.T) {
316316
unregisterDefaults(defaultSubsystem)
317317
}
318318

319+
func TestInvalidUTF8PathIsFixed(t *testing.T) {
320+
e := echo.New()
321+
322+
e.Use(NewMiddlewareWithConfig(MiddlewareConfig{Subsystem: defaultSubsystem}))
323+
e.GET("/metrics", NewHandler())
324+
325+
assert.Equal(t, http.StatusNotFound, request(e, "/../../WEB-INF/web.xml\xc0\x80.jsp"))
326+
327+
s, code := requestBody(e, "/metrics")
328+
assert.Equal(t, http.StatusOK, code)
329+
assert.Contains(t, s, fmt.Sprintf(`%s_request_duration_seconds_count{code="404",host="example.com",method="GET",url="/../../WEB-INF/web.xml�.jsp"} 1`, defaultSubsystem))
330+
331+
unregisterDefaults(defaultSubsystem)
332+
}
333+
319334
func requestBody(e *echo.Echo, path string) (string, int) {
320335
req := httptest.NewRequest(http.MethodGet, path, nil)
321336
rec := httptest.NewRecorder()

0 commit comments

Comments
 (0)