1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-24 05:17:03 +00:00

add a new simple, builtin requestid middleware (makes use of the Context.SetID/GetID methods too)

Former-commit-id: d46bce7c1964adada01934aa95daf389c141defc
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-05-28 16:20:58 +03:00
parent d556cfc39a
commit 9e5672da25
13 changed files with 170 additions and 21 deletions

View File

@@ -0,0 +1,82 @@
package requestid
import (
"github.com/kataras/iris/v12/context"
"github.com/google/uuid"
)
func init() {
context.SetHandlerName("iris/middleware/requestid.*", "iris.request.id")
}
const xRequestIDHeaderValue = "X-Request-ID"
// Generator defines the function which should extract or generate
// a Request ID. See `DefaultGenerator` and `New` package-level functions.
type Generator func(ctx context.Context) string
// DefaultGenerator is the default `Generator` that is used
// when nil is passed on `New` package-level function.
// It extracts the ID from the "X-Request-ID" request header value
// or, if missing, it generates a new UUID(v4) and sets the header and context value.
//
// See `Get` package-level function too.
var DefaultGenerator Generator = func(ctx context.Context) string {
id := ctx.GetHeader(xRequestIDHeaderValue)
if id == "" {
uid, err := uuid.NewRandom()
if err != nil {
ctx.StopWithStatus(500)
return ""
}
id = uid.String()
ctx.Header(xRequestIDHeaderValue, id)
}
return id
}
// New returns a new request id middleware.
// It accepts an ID Generator.
// The Generator can stop the handlers chain with an error or
// return a valid ID (string).
// If it's nil then the `DefaultGenerator` will be used instead.
func New(gen Generator) context.Handler {
if gen == nil {
gen = DefaultGenerator
}
return func(ctx context.Context) {
if Get(ctx) != "" {
ctx.Next()
return
}
id := gen(ctx)
if ctx.IsStopped() {
// ctx.Next checks that
// but we don't want to call SetID if generator failed.
return
}
ctx.SetID(id)
ctx.Next()
}
}
// Get returns the Request ID or empty string.
//
// A shortcut of `context.GetID().(string)`.
func Get(ctx context.Context) string {
v := ctx.GetID()
if v != nil {
if id, ok := v.(string); ok {
return id
}
}
return ""
}

View File

@@ -0,0 +1,63 @@
package requestid_test
import (
"testing"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/httptest"
"github.com/kataras/iris/v12/middleware/requestid"
)
func TestRequestID(t *testing.T) {
app := iris.New()
h := func(ctx iris.Context) {
ctx.WriteString(requestid.Get(ctx))
}
def := app.Party("/default")
{
def.Use(requestid.New(nil))
def.Get("/", h)
}
const expectedCustomID = "my_id"
custom := app.Party("/custom")
{
customGen := func(ctx context.Context) string {
return expectedCustomID
}
custom.Use(requestid.New(customGen))
custom.Get("/", h)
}
const expectedErrMsg = "no id"
customWithErr := app.Party("/custom_err")
{
customGen := func(ctx context.Context) string {
ctx.StopWithText(iris.StatusUnauthorized, expectedErrMsg)
return ""
}
customWithErr.Use(requestid.New(customGen))
customWithErr.Get("/", h)
}
const expectedCustomIDFromOtherMiddleware = "my custom id"
changeID := app.Party("/custom_change_id")
{
changeID.Use(func(ctx iris.Context) {
ctx.SetID(expectedCustomIDFromOtherMiddleware)
ctx.Next()
})
changeID.Use(requestid.New(nil))
changeID.Get("/", h)
}
e := httptest.New(t, app)
e.GET("/default").Expect().Status(httptest.StatusOK).Body().NotEmpty()
e.GET("/custom").Expect().Status(httptest.StatusOK).Body().Equal(expectedCustomID)
e.GET("/custom_err").Expect().Status(httptest.StatusUnauthorized).Body().Equal(expectedErrMsg)
e.GET("/custom_change_id").Expect().Status(httptest.StatusOK).Body().Equal(expectedCustomIDFromOtherMiddleware)
}