mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-12 16:04:25 +00:00
84 lines
2.5 KiB
Go
84 lines
2.5 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// A panic has to answer the request the same way gin's own recovery did, or
|
|
// swapping the two turns a 500 into a hung connection.
|
|
func TestRecoveryStillReturns500(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
r := gin.New()
|
|
r.Use(Recovery())
|
|
r.GET("/boom", func(*gin.Context) { panic("boom") })
|
|
|
|
rec := httptest.NewRecorder()
|
|
r.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/boom", nil))
|
|
|
|
if rec.Code != http.StatusInternalServerError {
|
|
t.Fatalf("status = %d, want 500", rec.Code)
|
|
}
|
|
}
|
|
|
|
// The tags are the whole point of reporting a panic rather than logging it: an
|
|
// issue nobody can tie to a route, a request id or a workspace is an issue
|
|
// nobody can act on.
|
|
func TestRequestTagsCarryTheIds(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
orgID := uuid.New()
|
|
|
|
var tags map[string]string
|
|
r := gin.New()
|
|
r.GET("/v1/campaigns/:id", func(c *gin.Context) {
|
|
c.Set(RequestIDContextKey, "req-123")
|
|
c.Set(OrganizationIDKey, orgID)
|
|
c.Set(UserIDKey, "user-abc")
|
|
tags = requestTags(c)
|
|
c.Status(http.StatusOK)
|
|
})
|
|
|
|
rec := httptest.NewRecorder()
|
|
r.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/v1/campaigns/"+uuid.NewString()+"?token=secret", nil))
|
|
|
|
want := map[string]string{
|
|
"http_method": http.MethodGet,
|
|
// The pattern, not the path: one issue per route, and the id in the
|
|
// URL never becomes part of the issue.
|
|
"http_route": "/v1/campaigns/:id",
|
|
"request_id": "req-123",
|
|
"organization_id": orgID.String(),
|
|
"user_id": "user-abc",
|
|
}
|
|
if len(tags) != len(want) {
|
|
t.Fatalf("tags = %v, want exactly %v", tags, want)
|
|
}
|
|
for key, value := range want {
|
|
if tags[key] != value {
|
|
t.Errorf("%s = %q, want %q", key, tags[key], value)
|
|
}
|
|
}
|
|
}
|
|
|
|
// An unmatched path is attacker-supplied, so it must not reach the report and
|
|
// mint one issue per probe. An unauthenticated request carries no ids either.
|
|
func TestRequestTagsOnAnUnmatchedPath(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
|
c.Request = httptest.NewRequest(http.MethodGet, "/wp-admin/setup-config.php", nil)
|
|
|
|
tags := requestTags(c)
|
|
if tags["http_route"] != "unmatched" {
|
|
t.Errorf("http_route = %q, want unmatched", tags["http_route"])
|
|
}
|
|
for _, key := range []string{"request_id", "organization_id", "user_id"} {
|
|
if _, ok := tags[key]; ok {
|
|
t.Errorf("%s was tagged on an unauthenticated request", key)
|
|
}
|
|
}
|
|
}
|