From 45426e39a36701dabb5326ec4a84444894badfd2 Mon Sep 17 00:00:00 2001 From: Bobby <30593201+luciferreeves@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:24:19 +0530 Subject: Implement request middleware enhancements: add BuildRequest function and improve request context handling --- middleware/request.go | 3 +- utils/meta/builder.go | 20 +++++++++ utils/meta/facade.go | 1 + utils/meta/request.go | 103 ++++++++++++++++++++++++++++++++++++++++++++ utils/meta/types.go | 16 +++++++ utils/meta/utils.go | 40 +++++++++++++++++ utils/meta/value.go | 9 ++++ utils/shortcuts/response.go | 22 ++++++++++ 8 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 utils/meta/builder.go create mode 100644 utils/meta/facade.go create mode 100644 utils/meta/request.go create mode 100644 utils/meta/types.go create mode 100644 utils/meta/utils.go create mode 100644 utils/meta/value.go create mode 100644 utils/shortcuts/response.go diff --git a/middleware/request.go b/middleware/request.go index 7d7d273..86fa2ee 100644 --- a/middleware/request.go +++ b/middleware/request.go @@ -10,7 +10,8 @@ const requestKey = "__request_ctx" func request() fiber.Handler { return func(c *fiber.Ctx) error { - c.Locals(requestKey, meta.Request(c)) + req := meta.BuildRequest(c) + c.Locals(requestKey, req) return c.Next() } } diff --git a/utils/meta/builder.go b/utils/meta/builder.go new file mode 100644 index 0000000..8e0ad8f --- /dev/null +++ b/utils/meta/builder.go @@ -0,0 +1,20 @@ +package meta + +import ( + "metachan/types" + + "github.com/gofiber/fiber/v2" +) + +func BuildRequest(c *fiber.Ctx) types.Request { + return types.Request{ + Path: c.Path(), + Method: c.Method(), + Query: buildQueryParams(c), + Params: buildRouteParams(c), + Headers: buildHeaders(c), + QueryString: string(c.Request().URI().QueryString()), + IP: c.IP(), + URL: c.OriginalURL(), + } +} diff --git a/utils/meta/facade.go b/utils/meta/facade.go new file mode 100644 index 0000000..5c21d74 --- /dev/null +++ b/utils/meta/facade.go @@ -0,0 +1 @@ +package meta diff --git a/utils/meta/request.go b/utils/meta/request.go new file mode 100644 index 0000000..7325a44 --- /dev/null +++ b/utils/meta/request.go @@ -0,0 +1,103 @@ +package meta + +import ( + "metachan/types" + "metachan/utils/logger" + + "github.com/gofiber/fiber/v2" +) + +const requestKey = "__request_ctx" + +func Request(c *fiber.Ctx) facade { + req, ok := c.Locals(requestKey).(types.Request) + if !ok { + logger.Errorf("META", "RequestContext missing in fiber locals") + return facade{} + } + return facade{req: req} +} + +func (f facade) Param(key string) (string, bool) { + for _, p := range f.req.Params { + if p.Key == key { + return p.Value, true + } + } + return "", false +} + +func (f facade) Query(key string) (string, bool) { + for _, q := range f.req.Query { + if q.Key == key { + return q.Value, true + } + } + return "", false +} + +func (f facade) Header(key string) (string, bool) { + for _, h := range f.req.Headers { + if h.Key == key { + return h.Value, true + } + } + return "", false +} + +func (r required) Param(key string) string { + for _, p := range r.req.Params { + if p.Key == key { + return p.Value + } + } + logger.Errorf("META", "missing required param: %s", key) + return "" +} + +func (r required) Query(key string) string { + for _, q := range r.req.Query { + if q.Key == key { + return q.Value + } + } + logger.Errorf("META", "missing required query: %s", key) + return "" +} + +func (r required) Header(key string) string { + for _, h := range r.req.Headers { + if h.Key == key { + return h.Value + } + } + logger.Errorf("META", "missing required header: %s", key) + return "" +} + +func (d withDefault) Param(key string) string { + for _, p := range d.req.Params { + if p.Key == key { + return p.Value + } + } + return d.def +} + +func (d withDefault) Query(key string) string { + for _, q := range d.req.Query { + if q.Key == key { + return q.Value + } + } + return d.def +} + +func (d withDefault) Header(key string) string { + for _, h := range d.req.Headers { + if h.Key == key { + return h.Value + } + } + return d.def +} diff --git a/utils/meta/types.go b/utils/meta/types.go new file mode 100644 index 0000000..043255b --- /dev/null +++ b/utils/meta/types.go @@ -0,0 +1,16 @@ +package meta + +import "metachan/types" + +type facade struct { + req types.Request +} + +type required struct { + req types.Request +} + +type withDefault struct { + req types.Request + def string +} diff --git a/utils/meta/utils.go b/utils/meta/utils.go new file mode 100644 index 0000000..a821447 --- /dev/null +++ b/utils/meta/utils.go @@ -0,0 +1,40 @@ +package meta + +import ( + "metachan/types" + + "github.com/gofiber/fiber/v2" +) + +func buildQueryParams(c *fiber.Ctx) []types.HTTPParam { + params := make([]types.HTTPParam, 0) + c.Request().URI().QueryArgs().VisitAll(func(k, v []byte) { + params = append(params, types.HTTPParam{ + Key: string(k), + Value: string(v), + }) + }) + return params +} + +func buildRouteParams(c *fiber.Ctx) []types.HTTPParam { + params := make([]types.HTTPParam, 0) + for k, v := range c.AllParams() { + params = append(params, types.HTTPParam{ + Key: k, + Value: v, + }) + } + return params +} + +func buildHeaders(c *fiber.Ctx) []types.HTTPParam { + params := make([]types.HTTPParam, 0) + c.Request().Header.VisitAll(func(k, v []byte) { + params = append(params, types.HTTPParam{ + Key: string(k), + Value: string(v), + }) + }) + return params +} diff --git a/utils/meta/value.go b/utils/meta/value.go new file mode 100644 index 0000000..1572066 --- /dev/null +++ b/utils/meta/value.go @@ -0,0 +1,9 @@ +package meta + +func (f facade) MustHave() required { + return required{req: f.req} +} + +func (f facade) Default(def string) withDefault { + return withDefault{req: f.req, def: def} +} diff --git a/utils/shortcuts/response.go b/utils/shortcuts/response.go new file mode 100644 index 0000000..c5a7a1c --- /dev/null +++ b/utils/shortcuts/response.go @@ -0,0 +1,22 @@ +package shortcuts + +import "github.com/gofiber/fiber/v2" + +type response struct { + ctx *fiber.Ctx + data any + status int +} + +func Response(ctx *fiber.Ctx, data any) *response { + return &response{ + ctx: ctx, + data: data, + status: fiber.StatusOK, + } +} + +func (r *response) As(status int) error { + r.status = status + return r.ctx.Status(status).JSON(r.data) +} -- cgit v1.2.3