Skip to content
This repository has been archived by the owner on May 19, 2023. It is now read-only.

Expand unit-tests for the middleware, fix panic caused by empty default configuration #82

Merged
merged 2 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
go-version:
- 1.16.x
- 1.18.x
- 1.19.x
platform:
- ubuntu-latest
- windows-latest
Expand Down
8 changes: 7 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,26 @@ type Config struct {
func New(config ...Config) fiber.Handler {
// Init config
var cfg Config

if len(config) > 0 {
cfg = config[0]
} else {
cfg = Config{}
}

if cfg.StatusCode == 0 {
cfg.StatusCode = 302 // Temporary Redirect
}
cfg = config[0]

cfg.rulesRegex = map[*regexp.Regexp]string{}

// Initialize
for k, v := range cfg.Rules {
k = strings.Replace(k, "*", "(.*)", -1)
k = k + "$"
cfg.rulesRegex[regexp.MustCompile(k)] = v
}

// Middleware function
return func(c *fiber.Ctx) error {
// Filter request to skip middleware
Expand Down
222 changes: 200 additions & 22 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)

func Test_Redirect(t *testing.T) {
Expand All @@ -18,32 +19,32 @@ func Test_Redirect(t *testing.T) {
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: 301,
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(New(Config{
Rules: map[string]string{
"/default/*": "fiber.wiki",
},
StatusCode: 307,
StatusCode: fiber.StatusTemporaryRedirect,
}))
app.Use(New(Config{
Rules: map[string]string{
"/redirect/*": "$1",
},
StatusCode: 303,
StatusCode: fiber.StatusSeeOther,
}))
app.Use(New(Config{
Rules: map[string]string{
"/pattern/*": "golang.org",
},
StatusCode: 302,
StatusCode: fiber.StatusFound,
}))

app.Use(New(Config{
Rules: map[string]string{
"/": "/swagger",
},
StatusCode: 301,
StatusCode: fiber.StatusMovedPermanently,
}))

app.Get("/api/*", func(c *fiber.Ctx) error {
Expand All @@ -61,66 +62,243 @@ func Test_Redirect(t *testing.T) {
statusCode int
}{
{
name: "should be returns status 302 without a wildcard",
name: "should be returns status StatusFound without a wildcard",
url: "/default",
redirectTo: "google.com",
statusCode: 301,
statusCode: fiber.StatusMovedPermanently,
},
{
name: "should be returns status 307 using wildcard",
name: "should be returns status StatusTemporaryRedirect using wildcard",
url: "/default/xyz",
redirectTo: "fiber.wiki",
statusCode: 307,
statusCode: fiber.StatusTemporaryRedirect,
},
{
name: "should be returns status 303 without set redirectTo to use the default",
name: "should be returns status StatusSeeOther without set redirectTo to use the default",
url: "/redirect/github.com/gofiber/redirect",
redirectTo: "github.com/gofiber/redirect",
statusCode: 303,
statusCode: fiber.StatusSeeOther,
},
{
name: "should return the status code default",
url: "/pattern/xyz",
redirectTo: "golang.org",
statusCode: 302,
statusCode: fiber.StatusFound,
},
{
name: "access URL without rule",
url: "/new",
statusCode: 200,
statusCode: fiber.StatusOK,
},
{
name: "redirect to swagger route",
url: "/",
redirectTo: "/swagger",
statusCode: 301,
statusCode: fiber.StatusMovedPermanently,
},
{
name: "no redirect to swagger route",
url: "/api/",
statusCode: 200,
statusCode: fiber.StatusOK,
},
{
name: "no redirect to swagger route #2",
url: "/api/test",
statusCode: 200,
statusCode: fiber.StatusOK,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req, _ := http.NewRequest("GET", tt.url, nil)
req.Header.Set("Location", "github.com/gofiber/redirect")
resp, err := app.Test(req)

if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != tt.statusCode {
t.Fatalf(`%s: StatusCode: got %v - expected %v`, t.Name(), resp.StatusCode, tt.statusCode)
}
if resp.Header.Get("Location") != tt.redirectTo {
t.Fatalf(`%s: Expecting Location: %s`, t.Name(), tt.redirectTo)
}

utils.AssertEqual(t, tt.statusCode, resp.StatusCode)
utils.AssertEqual(t, tt.redirectTo, resp.Header.Get("Location"))
})
}
}

func Test_Filter(t *testing.T) {
//Case 1 : filter function always returns true
app := *fiber.New()
app.Use(New(Config{
Filter: func(*fiber.Ctx) bool {
return true
},
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))

app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

req, _ := http.NewRequest("GET", "/default", nil)
resp, err := app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

//Case 2 : filter function always returns false
app = *fiber.New()
app.Use(New(Config{
Filter: func(*fiber.Ctx) bool {
return false
},
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))

req, _ = http.NewRequest("GET", "/default", nil)
resp, err = app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusMovedPermanently, resp.StatusCode)
utils.AssertEqual(t, "google.com", resp.Header.Get("Location"))
}

func Test_NoRules(t *testing.T) {
// Case 1: No rules with default route defined
app := *fiber.New()

app.Use(New(Config{
StatusCode: fiber.StatusMovedPermanently,
}))

app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

req, _ := http.NewRequest("GET", "/default", nil)
resp, err := app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

// Case 2: No rules and no default route defined
app = *fiber.New()

app.Use(New(Config{
StatusCode: fiber.StatusMovedPermanently,
}))

req, _ = http.NewRequest("GET", "/default", nil)
resp, err = app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode)
}

func Test_DefaultConfig(t *testing.T) {
// Case 1: Default config and no default route
app := *fiber.New()

app.Use(New())

req, _ := http.NewRequest("GET", "/default", nil)
resp, err := app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode)

// Case 2: Default config and default route
app = *fiber.New()

app.Use(New())
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

req, _ = http.NewRequest("GET", "/default", nil)
resp, err = app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
}

func Test_RegexRules(t *testing.T) {
// Case 1: Rules regex is empty
app := *fiber.New()
app.Use(New(Config{
Rules: map[string]string{},
StatusCode: fiber.StatusMovedPermanently,
}))

app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

req, _ := http.NewRequest("GET", "/default", nil)
resp, err := app.Test(req)

if err != nil {
t.Error(err)
}
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

// Case 2: Rules regex map contains valid regex and well-formed replacement URLs
app = *fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))

app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

req, _ = http.NewRequest("GET", "/default", nil)
resp, err = app.Test(req)

if err != nil {
t.Error(err)
}

utils.AssertEqual(t, fiber.StatusMovedPermanently, resp.StatusCode)
utils.AssertEqual(t, "google.com", resp.Header.Get("Location"))

// Case 3: Test invalid regex throws panic
defer func() {
if r := recover(); r != nil {
t.Log("Recovered from invalid regex: ", r)
}
}()

app = *fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"(": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
t.Error("Expected panic, got nil")
}