mirror of
https://github.com/gofiber/fiber.git
synced 2025-02-07 04:51:34 +00:00
* Update pull_request_template.md * Update v3-changes.md * Update CONTRIBUTING.md (#2752) Grammar correction. * chore(encryptcookie)!: update default config (#2753) * chore(encryptcookie)!: update default config docs(encryptcookie): enhance documentation and examples BREAKING CHANGE: removed the hardcoded "csrf_" from the Except. * docs(encryptcookie): reads or modifies cookies * chore(encryptcookie): csrf config example * docs(encryptcookie): md table spacing * build(deps): bump actions/setup-go from 4 to 5 (#2754) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🩹 middleware/logger/: log client IP address by default (#2755) * middleware/logger: Log client IP address by default. * Update doc. * fix: don't constrain middlewares' context-keys to strings 🐛 (#2751) * Revert "Revert "🐛 requestid.Config.ContextKey is interface{} (#2369)" (#2742)" This reverts commit 28be17f929cfa7d3c27dd292fc3956f2f9882e22. * fix: request ContextKey default value condition Should check for `nil` since it is `any`. * fix: don't constrain middlewares' context-keys to strings `context` recommends using "unexported type" as context keys to avoid collisions https://pkg.go.dev/github.com/gofiber/fiber/v2#Ctx.Locals. The official go blog also recommends this https://go.dev/blog/context. `fiber.Ctx.Locals(key any, value any)` correctly allows consumers to use unexported types or e.g. strings. But some fiber middlewares constrain their context-keys to `string` in their "default config structs", making it impossible to use unexported types. This PR removes the `string` _constraint_ from all middlewares, allowing to now use unexported types as per the official guidelines. However the default value is still a string, so it's not a breaking change, and anyone still using strings as context keys is not affected. * 📚 Update app.md for indentation (#2761) Update app.md for indentation * build(deps): bump github.com/google/uuid from 1.4.0 to 1.5.0 (#2762) Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/google/uuid/releases) - [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: github.com/google/uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github/codeql-action from 2 to 3 (#2763) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Changing default log output (#2730) changing default log output Closes #2729 * Update hooks.md fix wrong hooks signature * 🩹 Fix: CORS middleware should use the defined AllowedOriginsFunc config when AllowedOrigins is empty (#2771) * 🐛 [Bug]: Adaptator + otelfiber issue #2641 (#2772) * 🩹🚨 - fix for redirect with query params (#2748) * redirect with query params did not work, fix it and add test for it * redirect middleware - fix test typo * ♻️ logger/middleware colorize logger error message #2593 (#2773) * ✨ feat: add liveness and readiness checks (#2509) * ✨ feat: add liveness and readiness checkers * 📝 docs: add docs for liveness and readiness * ✨ feat: add options method for probe checkers * ✅ tests: add tests for liveness and readiness * ♻️ refactor: change default endpoint values * ♻️ refactor: change default value for liveness endpoint * 📝 docs: add return status for liveness and readiness probes * ♻️ refactor: change probechecker to middleware * 📝 docs: move docs to middleware session * ♻️ refactor: apply gofumpt formatting * ♻️ refactor: remove unused parameter * split config and apply a review * apply reviews and add testcases * add benchmark * cleanup * rename middleware * fix linter * Update docs and config values * Revert change to IsReady * Updates based on code review * Update docs to match other middlewares --------- Co-authored-by: Muhammed Efe Cetin <efectn@protonmail.com> Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Co-authored-by: Juan Calderon-Perez <jgcalderonperez@protonmail.com> * prepare release v2.52.0 - add more Parser tests * fix healthcheck.md * configure workflows for V2 branch * configure workflows for V2 branch * Fix default value to false in docs of QueryBool (#2811) fix default value to false in docs of QueryBool * update queryParser config * Update ctx.md * Update routing.md * merge v2 in v3 * merge v2 in v3 * lint fixes * 📚 Doc: Fix code snippet indentation in /docs/api/middleware/keyauth.md Removes an an extra level of indentation in line 51 of `keyauth.md` [here](https://github.com/gofiber/fiber/blob/v2/docs/api/middleware/keyauth.md?plain=1#L51) * fix: healthcheck middleware not working with route group (#2863) * fix: healthcheck middleware not working with route group * perf: change verification method to improve perf * Update healthcheck_test.go * test: add not matching route test for strict routing * add more test cases * correct tests * correct test helpers * correct tests * correct tests --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Co-authored-by: René Werner <rene@gofiber.io> * merge v2 in v3 * Merge pull request from GHSA-fmg4-x8pw-hjhg * Enforce Wildcard Origins with AllowCredentials check * Expand unit-tests, fix issues with subdomains logic, update docs * Update cors.md * Added test using localhost, ipv4, and ipv6 address * improve documentation markdown --------- Co-authored-by: René Werner <rene@gofiber.io> * Update app.go prepare release v2.52.1 * fix cors domain normalize * fix sync-docs workflow * test: fix failing tests * fix sync-docs workflow * test: cors middleware use testify require * chore: fix lint warnings * chore: revert test isolation. * fixed the fasthttp ctx race condition problem * Update middleware/cors/utils.go Co-authored-by: Renan Bastos <renanbastos.tec@gmail.com> * fix sync_docs.sh * fix review comments/hints * fix review comments/hints * stabilize Test_Proxy_Timeout_Slow_Server test * stabilize Test_Proxy_.* tests * ignore bodyclose linter for tests use http.NoBody instead of nil * revert(tests): undo http.NoBody usage * fix(ctx pool): postpone the reset for some values shortly before the release in the pool * refactor(tests): use testify panic method instead of custom solution --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tokelo-12 <113810058+tokelo-12@users.noreply.github.com> Co-authored-by: Jason McNeil <sixcolors@mac.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: iRedMail <2048991+iredmail@users.noreply.github.com> Co-authored-by: Benjamin Grosse <ste3ls@gmail.com> Co-authored-by: Mehmet Firat KOMURCU <mehmetfiratkomurcu@hotmail.com> Co-authored-by: Bruno <bdm2943@icloud.com> Co-authored-by: Muhammad Kholid B <muhammadkholidb@gmail.com> Co-authored-by: gilwo <gilwo@users.noreply.github.com> Co-authored-by: Lucas Lemos <lucashenriqueblemos@gmail.com> Co-authored-by: Muhammed Efe Cetin <efectn@protonmail.com> Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Co-authored-by: Juan Calderon-Perez <jgcalderonperez@protonmail.com> Co-authored-by: Jongmin Kim <kjongmin26@gmail.com> Co-authored-by: Giovanni Rivera <rivera.giovanni271@gmail.com> Co-authored-by: Renan Bastos <renanbastos.tec@gmail.com>
604 lines
16 KiB
Go
604 lines
16 KiB
Go
// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
|
|
// 🤖 Github Repository: https://github.com/gofiber/fiber
|
|
// 📌 API Documentation: https://docs.gofiber.io
|
|
|
|
package fiber
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// go test -run Test_App_Mount
|
|
func Test_App_Mount(t *testing.T) {
|
|
t.Parallel()
|
|
micro := New()
|
|
micro.Get("/doe", func(c Ctx) error {
|
|
return c.SendStatus(StatusOK)
|
|
})
|
|
|
|
app := New()
|
|
app.Use("/john", micro)
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/john/doe", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
require.Equal(t, uint32(1), app.handlersCount)
|
|
}
|
|
|
|
func Test_App_Mount_RootPath_Nested(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
dynamic := New()
|
|
apiserver := New()
|
|
|
|
apiroutes := apiserver.Group("/v1")
|
|
apiroutes.Get("/home", func(c Ctx) error {
|
|
return c.SendString("home")
|
|
})
|
|
|
|
dynamic.Use("/api", apiserver)
|
|
app.Use("/", dynamic)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/api/v1/home", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
require.Equal(t, uint32(1), app.handlersCount)
|
|
}
|
|
|
|
// go test -run Test_App_Mount_Nested
|
|
func Test_App_Mount_Nested(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
one := New()
|
|
two := New()
|
|
three := New()
|
|
|
|
two.Use("/three", three)
|
|
app.Use("/one", one)
|
|
one.Use("/two", two)
|
|
|
|
one.Get("/doe", func(c Ctx) error {
|
|
return c.SendStatus(StatusOK)
|
|
})
|
|
|
|
two.Get("/nested", func(c Ctx) error {
|
|
return c.SendStatus(StatusOK)
|
|
})
|
|
|
|
three.Get("/test", func(c Ctx) error {
|
|
return c.SendStatus(StatusOK)
|
|
})
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/one/doe", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
resp, err = app.Test(httptest.NewRequest(MethodGet, "/one/two/nested", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
resp, err = app.Test(httptest.NewRequest(MethodGet, "/one/two/three/test", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
require.Equal(t, uint32(3), app.handlersCount)
|
|
require.Equal(t, uint32(3), app.routesCount)
|
|
}
|
|
|
|
// go test -run Test_App_Mount_Express_Behavior
|
|
func Test_App_Mount_Express_Behavior(t *testing.T) {
|
|
t.Parallel()
|
|
createTestHandler := func(body string) func(c Ctx) error {
|
|
return func(c Ctx) error {
|
|
return c.SendString(body)
|
|
}
|
|
}
|
|
testEndpoint := func(app *App, route, expectedBody string, expectedStatusCode int) {
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, route, nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, expectedStatusCode, resp.StatusCode, "Status code")
|
|
require.Equal(t, expectedBody, string(body), "Unexpected response body")
|
|
}
|
|
|
|
app := New()
|
|
subApp := New()
|
|
// app setup
|
|
{
|
|
subApp.Get("/hello", createTestHandler("subapp hello!"))
|
|
subApp.Get("/world", createTestHandler("subapp world!")) // <- wins
|
|
|
|
app.Get("/hello", createTestHandler("app hello!")) // <- wins
|
|
app.Use("/", subApp) // <- subApp registration
|
|
app.Get("/world", createTestHandler("app world!"))
|
|
|
|
app.Get("/bar", createTestHandler("app bar!"))
|
|
subApp.Get("/bar", createTestHandler("subapp bar!")) // <- wins
|
|
|
|
subApp.Get("/foo", createTestHandler("subapp foo!")) // <- wins
|
|
app.Get("/foo", createTestHandler("app foo!"))
|
|
|
|
// 404 Handler
|
|
app.Use(func(c Ctx) error {
|
|
return c.SendStatus(StatusNotFound)
|
|
})
|
|
}
|
|
// expectation check
|
|
testEndpoint(app, "/world", "subapp world!", StatusOK)
|
|
testEndpoint(app, "/hello", "app hello!", StatusOK)
|
|
testEndpoint(app, "/bar", "subapp bar!", StatusOK)
|
|
testEndpoint(app, "/foo", "subapp foo!", StatusOK)
|
|
testEndpoint(app, "/unknown", ErrNotFound.Message, StatusNotFound)
|
|
|
|
require.Equal(t, uint32(9), app.handlersCount)
|
|
require.Equal(t, uint32(17), app.routesCount)
|
|
}
|
|
|
|
// go test -run Test_App_Mount_RoutePositions
|
|
func Test_App_Mount_RoutePositions(t *testing.T) {
|
|
t.Parallel()
|
|
testEndpoint := func(app *App, route, expectedBody string) {
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, route, nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
require.Equal(t, expectedBody, string(body), "Unexpected response body")
|
|
}
|
|
|
|
app := New()
|
|
subApp1 := New()
|
|
subApp2 := New()
|
|
// app setup
|
|
{
|
|
app.Use(func(c Ctx) error {
|
|
// set initial value
|
|
c.Locals("world", "world")
|
|
return c.Next()
|
|
})
|
|
app.Use("/subApp1", subApp1)
|
|
app.Use(func(c Ctx) error {
|
|
return c.Next()
|
|
})
|
|
app.Get("/bar", func(c Ctx) error {
|
|
return c.SendString("ok")
|
|
})
|
|
app.Use(func(c Ctx) error {
|
|
// is overwritten in case the positioning is not correct
|
|
c.Locals("world", "hello")
|
|
return c.Next()
|
|
})
|
|
methods := subApp2.Group("/subApp2")
|
|
methods.Get("/world", func(c Ctx) error {
|
|
v, ok := c.Locals("world").(string)
|
|
if !ok {
|
|
panic("unexpected data type")
|
|
}
|
|
return c.SendString(v)
|
|
})
|
|
app.Use("", subApp2)
|
|
}
|
|
|
|
testEndpoint(app, "/subApp2/world", "hello")
|
|
|
|
routeStackGET := app.Stack()[0]
|
|
require.True(t, routeStackGET[0].use)
|
|
require.Equal(t, "/", routeStackGET[0].path)
|
|
|
|
require.True(t, routeStackGET[1].use)
|
|
require.Equal(t, "/", routeStackGET[1].path)
|
|
require.Less(t, routeStackGET[0].pos, routeStackGET[1].pos, "wrong position of route 0")
|
|
|
|
require.False(t, routeStackGET[2].use)
|
|
require.Equal(t, "/bar", routeStackGET[2].path)
|
|
require.Less(t, routeStackGET[1].pos, routeStackGET[2].pos, "wrong position of route 1")
|
|
|
|
require.True(t, routeStackGET[3].use)
|
|
require.Equal(t, "/", routeStackGET[3].path)
|
|
require.Less(t, routeStackGET[2].pos, routeStackGET[3].pos, "wrong position of route 2")
|
|
|
|
require.False(t, routeStackGET[4].use)
|
|
require.Equal(t, "/subapp2/world", routeStackGET[4].path)
|
|
require.Less(t, routeStackGET[3].pos, routeStackGET[4].pos, "wrong position of route 3")
|
|
|
|
require.Len(t, routeStackGET, 5)
|
|
}
|
|
|
|
// go test -run Test_App_MountPath
|
|
func Test_App_MountPath(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
one := New()
|
|
two := New()
|
|
three := New()
|
|
|
|
two.Use("/three", three)
|
|
one.Use("/two", two)
|
|
app.Use("/one", one)
|
|
|
|
require.Equal(t, "/one", one.MountPath())
|
|
require.Equal(t, "/one/two", two.MountPath())
|
|
require.Equal(t, "/one/two/three", three.MountPath())
|
|
require.Equal(t, "", app.MountPath())
|
|
}
|
|
|
|
func Test_App_ErrorHandler_GroupMount(t *testing.T) {
|
|
t.Parallel()
|
|
micro := New(Config{
|
|
ErrorHandler: func(c Ctx, err error) error {
|
|
require.Equal(t, "0: GET error", err.Error())
|
|
return c.Status(500).SendString("1: custom error")
|
|
},
|
|
})
|
|
micro.Get("/doe", func(_ Ctx) error {
|
|
return errors.New("0: GET error")
|
|
})
|
|
|
|
app := New()
|
|
v1 := app.Group("/v1")
|
|
v1.Use("/john", micro)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/v1/john/doe", nil))
|
|
testErrorResponse(t, err, resp, "1: custom error")
|
|
}
|
|
|
|
func Test_App_ErrorHandler_GroupMountRootLevel(t *testing.T) {
|
|
t.Parallel()
|
|
micro := New(Config{
|
|
ErrorHandler: func(c Ctx, err error) error {
|
|
require.Equal(t, "0: GET error", err.Error())
|
|
return c.Status(500).SendString("1: custom error")
|
|
},
|
|
})
|
|
micro.Get("/john/doe", func(_ Ctx) error {
|
|
return errors.New("0: GET error")
|
|
})
|
|
|
|
app := New()
|
|
v1 := app.Group("/v1")
|
|
v1.Use("/", micro)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/v1/john/doe", nil))
|
|
testErrorResponse(t, err, resp, "1: custom error")
|
|
}
|
|
|
|
// go test -run Test_App_Group_Mount
|
|
func Test_App_Group_Mount(t *testing.T) {
|
|
t.Parallel()
|
|
micro := New()
|
|
micro.Get("/doe", func(c Ctx) error {
|
|
return c.SendStatus(StatusOK)
|
|
})
|
|
|
|
app := New()
|
|
v1 := app.Group("/v1")
|
|
v1.Use("/john", micro)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/v1/john/doe", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
require.Equal(t, uint32(1), app.handlersCount)
|
|
}
|
|
|
|
func Test_App_UseParentErrorHandler(t *testing.T) {
|
|
t.Parallel()
|
|
app := New(Config{
|
|
ErrorHandler: func(ctx Ctx, _ error) error {
|
|
return ctx.Status(500).SendString("hi, i'm a custom error")
|
|
},
|
|
})
|
|
|
|
fiber := New()
|
|
fiber.Get("/", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
|
|
app.Use("/api", fiber)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/api", nil))
|
|
testErrorResponse(t, err, resp, "hi, i'm a custom error")
|
|
}
|
|
|
|
func Test_App_UseMountedErrorHandler(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
|
|
fiber := New(Config{
|
|
ErrorHandler: func(c Ctx, _ error) error {
|
|
return c.Status(500).SendString("hi, i'm a custom error")
|
|
},
|
|
})
|
|
fiber.Get("/", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
|
|
app.Use("/api", fiber)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/api", nil))
|
|
testErrorResponse(t, err, resp, "hi, i'm a custom error")
|
|
}
|
|
|
|
func Test_App_UseMountedErrorHandlerRootLevel(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
|
|
fiber := New(Config{
|
|
ErrorHandler: func(c Ctx, _ error) error {
|
|
return c.Status(500).SendString("hi, i'm a custom error")
|
|
},
|
|
})
|
|
fiber.Get("/api", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
|
|
app.Use("/", fiber)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/api", nil))
|
|
testErrorResponse(t, err, resp, "hi, i'm a custom error")
|
|
}
|
|
|
|
func Test_App_UseMountedErrorHandlerForBestPrefixMatch(t *testing.T) {
|
|
t.Parallel()
|
|
app := New()
|
|
|
|
tsf := func(c Ctx, _ error) error {
|
|
return c.Status(200).SendString("hi, i'm a custom sub sub fiber error")
|
|
}
|
|
tripleSubFiber := New(Config{
|
|
ErrorHandler: tsf,
|
|
})
|
|
tripleSubFiber.Get("/", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
|
|
sf := func(c Ctx, _ error) error {
|
|
return c.Status(200).SendString("hi, i'm a custom sub fiber error")
|
|
}
|
|
subfiber := New(Config{
|
|
ErrorHandler: sf,
|
|
})
|
|
subfiber.Get("/", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
subfiber.Use("/third", tripleSubFiber)
|
|
|
|
f := func(c Ctx, _ error) error {
|
|
return c.Status(200).SendString("hi, i'm a custom error")
|
|
}
|
|
fiber := New(Config{
|
|
ErrorHandler: f,
|
|
})
|
|
fiber.Get("/", func(_ Ctx) error {
|
|
return errors.New("something happened")
|
|
})
|
|
fiber.Use("/sub", subfiber)
|
|
|
|
app.Use("/api", fiber)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/api/sub", nil))
|
|
require.NoError(t, err, "/api/sub req")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
b, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err, "iotuil.ReadAll()")
|
|
require.Equal(t, "hi, i'm a custom sub fiber error", string(b), "Response body")
|
|
|
|
resp2, err := app.Test(httptest.NewRequest(MethodGet, "/api/sub/third", nil))
|
|
require.NoError(t, err, "/api/sub/third req")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
b, err = io.ReadAll(resp2.Body)
|
|
require.NoError(t, err, "iotuil.ReadAll()")
|
|
require.Equal(t, "hi, i'm a custom sub sub fiber error", string(b), "Third fiber Response body")
|
|
}
|
|
|
|
// go test -run Test_Mount_Route_Names
|
|
func Test_Mount_Route_Names(t *testing.T) {
|
|
// create sub-app with 2 handlers:
|
|
subApp1 := New()
|
|
subApp1.Get("/users", func(c Ctx) error {
|
|
url, err := c.GetRouteURL("add-user", Map{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "/app1/users", url, "handler: app1.add-user") // the prefix is /app1 because of the mount
|
|
// if subApp1 is not mounted, expected url just /users
|
|
return nil
|
|
}).Name("get-users")
|
|
subApp1.Post("/users", func(c Ctx) error {
|
|
route := c.App().GetRoute("get-users")
|
|
require.Equal(t, MethodGet, route.Method, "handler: app1.get-users method")
|
|
require.Equal(t, "/app1/users", route.Path, "handler: app1.get-users path")
|
|
return nil
|
|
}).Name("add-user")
|
|
|
|
// create sub-app with 2 handlers inside a group:
|
|
subApp2 := New()
|
|
app2Grp := subApp2.Group("/users").Name("users.")
|
|
app2Grp.Get("", emptyHandler).Name("get")
|
|
app2Grp.Post("", emptyHandler).Name("add")
|
|
|
|
// put both sub-apps into root app
|
|
rootApp := New()
|
|
_ = rootApp.Use("/app1", subApp1)
|
|
_ = rootApp.Use("/app2", subApp2)
|
|
|
|
rootApp.startupProcess()
|
|
|
|
// take route directly from sub-app
|
|
route := subApp1.GetRoute("get-users")
|
|
require.Equal(t, MethodGet, route.Method)
|
|
require.Equal(t, "/users", route.Path)
|
|
|
|
route = subApp1.GetRoute("add-user")
|
|
require.Equal(t, MethodPost, route.Method)
|
|
require.Equal(t, "/users", route.Path)
|
|
|
|
// take route directly from sub-app with group
|
|
route = subApp2.GetRoute("users.get")
|
|
require.Equal(t, MethodGet, route.Method)
|
|
require.Equal(t, "/users", route.Path)
|
|
|
|
route = subApp2.GetRoute("users.add")
|
|
require.Equal(t, MethodPost, route.Method)
|
|
require.Equal(t, "/users", route.Path)
|
|
|
|
// take route from root app (using names of sub-apps)
|
|
route = rootApp.GetRoute("add-user")
|
|
require.Equal(t, MethodPost, route.Method)
|
|
require.Equal(t, "/app1/users", route.Path)
|
|
|
|
route = rootApp.GetRoute("users.add")
|
|
require.Equal(t, MethodPost, route.Method)
|
|
require.Equal(t, "/app2/users", route.Path)
|
|
|
|
// GetRouteURL inside handler
|
|
req := httptest.NewRequest(MethodGet, "/app1/users", nil)
|
|
resp, err := rootApp.Test(req)
|
|
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
|
|
// ctx.App().GetRoute() inside handler
|
|
req = httptest.NewRequest(MethodPost, "/app1/users", nil)
|
|
resp, err = rootApp.Test(req)
|
|
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
}
|
|
|
|
// go test -run Test_Ctx_Render_Mount
|
|
func Test_Ctx_Render_Mount(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
engine := &testTemplateEngine{}
|
|
err := engine.Load()
|
|
require.NoError(t, err)
|
|
|
|
sub := New(Config{
|
|
Views: engine,
|
|
})
|
|
|
|
sub.Get("/:name", func(c Ctx) error {
|
|
return c.Render("hello_world.tmpl", Map{
|
|
"Name": c.Params("name"),
|
|
})
|
|
})
|
|
|
|
app := New()
|
|
app.Use("/hello", sub)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/hello/a", nil))
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
require.NoError(t, err, "app.Test(req)")
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "<h1>Hello a!</h1>", string(body))
|
|
}
|
|
|
|
// go test -run Test_Ctx_Render_Mount_ParentOrSubHasViews
|
|
func Test_Ctx_Render_Mount_ParentOrSubHasViews(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
engine := &testTemplateEngine{}
|
|
err := engine.Load()
|
|
require.NoError(t, err)
|
|
|
|
engine2 := &testTemplateEngine{path: "testdata2"}
|
|
err = engine2.Load()
|
|
require.NoError(t, err)
|
|
|
|
engine3 := &testTemplateEngine{path: "testdata3"}
|
|
err = engine3.Load()
|
|
require.NoError(t, err)
|
|
|
|
sub := New(Config{
|
|
Views: engine3,
|
|
})
|
|
|
|
sub2 := New(Config{
|
|
Views: engine2,
|
|
})
|
|
|
|
app := New(Config{
|
|
Views: engine,
|
|
})
|
|
|
|
app.Get("/test", func(c Ctx) error {
|
|
return c.Render("index.tmpl", Map{
|
|
"Title": "Hello, World!",
|
|
})
|
|
})
|
|
|
|
sub.Get("/world/:name", func(c Ctx) error {
|
|
return c.Render("hello_world.tmpl", Map{
|
|
"Name": c.Params("name"),
|
|
})
|
|
})
|
|
|
|
sub2.Get("/moment", func(c Ctx) error {
|
|
return c.Render("bruh.tmpl", Map{})
|
|
})
|
|
|
|
sub.Use("/bruh", sub2)
|
|
app.Use("/hello", sub)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/hello/world/a", nil))
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
require.NoError(t, err, "app.Test(req)")
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "<h1>Hello a!</h1>", string(body))
|
|
|
|
resp, err = app.Test(httptest.NewRequest(MethodGet, "/test", nil))
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
require.NoError(t, err, "app.Test(req)")
|
|
|
|
body, err = io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "<h1>Hello, World!</h1>", string(body))
|
|
|
|
resp, err = app.Test(httptest.NewRequest(MethodGet, "/hello/bruh/moment", nil))
|
|
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
|
|
require.NoError(t, err, "app.Test(req)")
|
|
|
|
body, err = io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "<h1>I'm Bruh</h1>", string(body))
|
|
}
|
|
|
|
func Test_Ctx_Render_MountGroup(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
engine := &testTemplateEngine{}
|
|
err := engine.Load()
|
|
require.NoError(t, err)
|
|
|
|
micro := New(Config{
|
|
Views: engine,
|
|
})
|
|
|
|
micro.Get("/doe", func(c Ctx) error {
|
|
return c.Render("hello_world.tmpl", Map{
|
|
"Name": "doe",
|
|
})
|
|
})
|
|
|
|
app := New()
|
|
v1 := app.Group("/v1")
|
|
v1.Use("/john", micro)
|
|
|
|
resp, err := app.Test(httptest.NewRequest(MethodGet, "/v1/john/doe", nil))
|
|
require.NoError(t, err, "app.Test(req)")
|
|
require.Equal(t, 200, resp.StatusCode, "Status code")
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "<h1>Hello doe!</h1>", string(body))
|
|
}
|