mirror of https://github.com/gofiber/fiber.git
✨ enhancement: use msgp for flash message encoding/decoding (#3099)
* enhancement: use msgp for flash message encoding/decoding * add msgp tests * improve test coverage * improve test coverage * fix linter * update makefile * extend go generation process --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Co-authored-by: René <rene@gofiber.io>bind^2
parent
0fbb447679
commit
08d9fda631
14
Makefile
14
Makefile
|
@ -57,11 +57,9 @@ tidy:
|
||||||
betteralign:
|
betteralign:
|
||||||
go run github.com/dkorunic/betteralign/cmd/betteralign@latest -test_files -generated_files -apply ./...
|
go run github.com/dkorunic/betteralign/cmd/betteralign@latest -test_files -generated_files -apply ./...
|
||||||
|
|
||||||
## tidy: ⚡️ Generate msgp
|
## tidy: ⚡️ Generate msgp && interface implementations
|
||||||
.PHONY: msgp
|
.PHONY: generate
|
||||||
msgp:
|
generate:
|
||||||
go run github.com/tinylib/msgp@latest -file="middleware/cache/manager.go" -o="middleware/cache/manager_msgp.go" -tests=true -unexported
|
go install github.com/tinylib/msgp@latest
|
||||||
go run github.com/tinylib/msgp@latest -file="middleware/session/data.go" -o="middleware/session/data_msgp.go" -tests=true -unexported
|
go install github.com/vburenin/ifacemaker@975a95966976eeb2d4365a7fb236e274c54da64c
|
||||||
go run github.com/tinylib/msgp@latest -file="middleware/csrf/storage_manager.go" -o="middleware/csrf/storage_manager_msgp.go" -tests=true -unexported
|
go generate ./...
|
||||||
go run github.com/tinylib/msgp@latest -file="middleware/limiter/manager.go" -o="middleware/limiter/manager_msgp.go" -tests=true -unexported
|
|
||||||
go run github.com/tinylib/msgp@latest -file="middleware/idempotency/response.go" -o="middleware/idempotency/response_msgp.go" -tests=true -unexported
|
|
||||||
|
|
4
ctx.go
4
ctx.go
|
@ -63,7 +63,7 @@ type DefaultCtx struct {
|
||||||
pathOriginal string // Original HTTP path
|
pathOriginal string // Original HTTP path
|
||||||
pathBuffer []byte // HTTP path buffer
|
pathBuffer []byte // HTTP path buffer
|
||||||
detectionPathBuffer []byte // HTTP detectionPath buffer
|
detectionPathBuffer []byte // HTTP detectionPath buffer
|
||||||
redirectionMessages []string // Messages of the previous redirect
|
flashMessages redirectionMsgs // Flash messages
|
||||||
indexRoute int // Index of the current route
|
indexRoute int // Index of the current route
|
||||||
indexHandler int // Index of the current handler
|
indexHandler int // Index of the current handler
|
||||||
methodINT int // HTTP method INT equivalent
|
methodINT int // HTTP method INT equivalent
|
||||||
|
@ -1896,7 +1896,7 @@ func (c *DefaultCtx) release() {
|
||||||
c.route = nil
|
c.route = nil
|
||||||
c.fasthttp = nil
|
c.fasthttp = nil
|
||||||
c.bind = nil
|
c.bind = nil
|
||||||
c.redirectionMessages = c.redirectionMessages[:0]
|
c.flashMessages = c.flashMessages[:0]
|
||||||
c.viewBindMap = sync.Map{}
|
c.viewBindMap = sync.Map{}
|
||||||
if c.redirect != nil {
|
if c.redirect != nil {
|
||||||
ReleaseRedirect(c.redirect)
|
ReleaseRedirect(c.redirect)
|
||||||
|
|
|
@ -330,6 +330,7 @@ type Ctx interface {
|
||||||
Reset(fctx *fasthttp.RequestCtx)
|
Reset(fctx *fasthttp.RequestCtx)
|
||||||
// Release is a method to reset context fields when to use ReleaseCtx()
|
// Release is a method to reset context fields when to use ReleaseCtx()
|
||||||
release()
|
release()
|
||||||
|
getBody() []byte
|
||||||
// Methods to use with next stack.
|
// Methods to use with next stack.
|
||||||
getMethodINT() int
|
getMethodINT() int
|
||||||
getIndexRoute() int
|
getIndexRoute() int
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
// msgp -file="manager.go" -o="manager_msgp.go" -tests=true -unexported
|
// msgp -file="manager.go" -o="manager_msgp.go" -tests=true -unexported
|
||||||
//
|
//
|
||||||
//go:generate msgp
|
//go:generate msgp -o=manager_msgp.go -tests=true -unexported
|
||||||
type item struct {
|
type item struct {
|
||||||
headers map[string][]byte
|
headers map[string][]byte
|
||||||
body []byte
|
body []byte
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
// msgp -file="storage_manager.go" -o="storage_manager_msgp.go" -tests=true -unexported
|
// msgp -file="storage_manager.go" -o="storage_manager_msgp.go" -tests=true -unexported
|
||||||
//
|
//
|
||||||
//go:generate msgp
|
//go:generate msgp -o=storage_manager_msgp.go -tests=true -unexported
|
||||||
type item struct{}
|
type item struct{}
|
||||||
|
|
||||||
//msgp:ignore manager
|
//msgp:ignore manager
|
||||||
|
|
|
@ -3,7 +3,7 @@ package idempotency
|
||||||
// response is a struct that represents the response of a request.
|
// response is a struct that represents the response of a request.
|
||||||
// generation tool `go install github.com/tinylib/msgp@latest`
|
// generation tool `go install github.com/tinylib/msgp@latest`
|
||||||
//
|
//
|
||||||
//go:generate msgp -o=response_msgp.go -io=false -tests=true -unexported
|
//go:generate msgp -o=response_msgp.go -tests=true -unexported
|
||||||
type response struct {
|
type response struct {
|
||||||
Headers map[string][]string `msg:"hs"`
|
Headers map[string][]string `msg:"hs"`
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
// msgp -file="manager.go" -o="manager_msgp.go" -tests=false -unexported
|
// msgp -file="manager.go" -o="manager_msgp.go" -tests=false -unexported
|
||||||
//
|
//
|
||||||
//go:generate msgp
|
//go:generate msgp -o=manager_msgp.go -tests=false -unexported
|
||||||
type item struct {
|
type item struct {
|
||||||
currHits int
|
currHits int
|
||||||
prevHits int
|
prevHits int
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
// msgp -file="data.go" -o="data_msgp.go" -tests=true -unexported
|
// msgp -file="data.go" -o="data_msgp.go" -tests=true -unexported
|
||||||
//
|
//
|
||||||
//go:generate msgp
|
//go:generate msgp -o=data_msgp.go -tests=true -unexported
|
||||||
type data struct {
|
type data struct {
|
||||||
Data map[string]any
|
Data map[string]any
|
||||||
sync.RWMutex `msg:"-"`
|
sync.RWMutex `msg:"-"`
|
||||||
|
|
207
redirect.go
207
redirect.go
|
@ -6,7 +6,6 @@ package fiber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3/binder"
|
"github.com/gofiber/fiber/v3/binder"
|
||||||
|
@ -19,7 +18,7 @@ var redirectPool = sync.Pool{
|
||||||
New: func() any {
|
New: func() any {
|
||||||
return &Redirect{
|
return &Redirect{
|
||||||
status: StatusFound,
|
status: StatusFound,
|
||||||
oldInput: make(map[string]string, 0),
|
messages: make(redirectionMsgs, 0),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -32,12 +31,36 @@ const (
|
||||||
CookieDataAssigner = ":"
|
CookieDataAssigner = ":"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// redirectionMsgs is a struct that used to store flash messages and old input data in cookie using MSGP.
|
||||||
|
// msgp -file="redirect.go" -o="redirect_msgp.go" -unexported
|
||||||
|
//
|
||||||
|
//msgp:ignore Redirect RedirectConfig OldInputData FlashMessage
|
||||||
|
type redirectionMsg struct {
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
level uint8
|
||||||
|
isOldInput bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type redirectionMsgs []redirectionMsg
|
||||||
|
|
||||||
|
// OldInputData is a struct that holds the old input data.
|
||||||
|
type OldInputData struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlashMessage is a struct that holds the flash message data.
|
||||||
|
type FlashMessage struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
Level uint8
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect is a struct that holds the redirect data.
|
// Redirect is a struct that holds the redirect data.
|
||||||
type Redirect struct {
|
type Redirect struct {
|
||||||
c *DefaultCtx // Embed ctx
|
c *DefaultCtx // Embed ctx
|
||||||
oldInput map[string]string // Old input data
|
messages redirectionMsgs // Flash messages and old input data
|
||||||
|
|
||||||
messages []string // Flash messages
|
|
||||||
status int // Status code of redirection. Default: StatusFound
|
status int // Status code of redirection. Default: StatusFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,10 +94,6 @@ func ReleaseRedirect(r *Redirect) {
|
||||||
func (r *Redirect) release() {
|
func (r *Redirect) release() {
|
||||||
r.status = 302
|
r.status = 302
|
||||||
r.messages = r.messages[:0]
|
r.messages = r.messages[:0]
|
||||||
// reset map
|
|
||||||
for k := range r.oldInput {
|
|
||||||
delete(r.oldInput, k)
|
|
||||||
}
|
|
||||||
r.c = nil
|
r.c = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +109,28 @@ func (r *Redirect) Status(code int) *Redirect {
|
||||||
// They will be sent as a cookie.
|
// They will be sent as a cookie.
|
||||||
// You can get them by using: Redirect().Messages(), Redirect().Message()
|
// You can get them by using: Redirect().Messages(), Redirect().Message()
|
||||||
// Note: You must use escape char before using ',' and ':' chars to avoid wrong parsing.
|
// Note: You must use escape char before using ',' and ':' chars to avoid wrong parsing.
|
||||||
func (r *Redirect) With(key, value string) *Redirect {
|
func (r *Redirect) With(key, value string, level ...uint8) *Redirect {
|
||||||
r.messages = append(r.messages, key+CookieDataAssigner+value)
|
// Get level
|
||||||
|
var msgLevel uint8
|
||||||
|
if len(level) > 0 {
|
||||||
|
msgLevel = level[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override old message if exists
|
||||||
|
for i, msg := range r.messages {
|
||||||
|
if msg.key == key && !msg.isOldInput {
|
||||||
|
r.messages[i].value = value
|
||||||
|
r.messages[i].level = msgLevel
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.messages = append(r.messages, redirectionMsg{
|
||||||
|
key: key,
|
||||||
|
value: value,
|
||||||
|
level: msgLevel,
|
||||||
|
})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -105,28 +144,39 @@ func (r *Redirect) WithInput() *Redirect {
|
||||||
ctype := utils.ToLower(utils.UnsafeString(r.c.Context().Request.Header.ContentType()))
|
ctype := utils.ToLower(utils.UnsafeString(r.c.Context().Request.Header.ContentType()))
|
||||||
ctype = binder.FilterFlags(utils.ParseVendorSpecificContentType(ctype))
|
ctype = binder.FilterFlags(utils.ParseVendorSpecificContentType(ctype))
|
||||||
|
|
||||||
|
oldInput := make(map[string]string)
|
||||||
switch ctype {
|
switch ctype {
|
||||||
case MIMEApplicationForm:
|
case MIMEApplicationForm:
|
||||||
_ = r.c.Bind().Form(r.oldInput) //nolint:errcheck // not needed
|
_ = r.c.Bind().Form(oldInput) //nolint:errcheck // not needed
|
||||||
case MIMEMultipartForm:
|
case MIMEMultipartForm:
|
||||||
_ = r.c.Bind().MultipartForm(r.oldInput) //nolint:errcheck // not needed
|
_ = r.c.Bind().MultipartForm(oldInput) //nolint:errcheck // not needed
|
||||||
default:
|
default:
|
||||||
_ = r.c.Bind().Query(r.oldInput) //nolint:errcheck // not needed
|
_ = r.c.Bind().Query(oldInput) //nolint:errcheck // not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add old input data
|
||||||
|
for k, v := range oldInput {
|
||||||
|
r.messages = append(r.messages, redirectionMsg{
|
||||||
|
key: k,
|
||||||
|
value: v,
|
||||||
|
isOldInput: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Messages Get flash messages.
|
// Messages Get flash messages.
|
||||||
func (r *Redirect) Messages() map[string]string {
|
func (r *Redirect) Messages() []FlashMessage {
|
||||||
msgs := r.c.redirectionMessages
|
flashMessages := make([]FlashMessage, 0)
|
||||||
flashMessages := make(map[string]string, len(msgs))
|
|
||||||
|
|
||||||
for _, msg := range msgs {
|
for _, msg := range r.c.flashMessages {
|
||||||
k, v := parseMessage(msg)
|
if !msg.isOldInput {
|
||||||
|
flashMessages = append(flashMessages, FlashMessage{
|
||||||
if !strings.HasPrefix(k, OldInputDataPrefix) {
|
Key: msg.key,
|
||||||
flashMessages[k] = v
|
Value: msg.value,
|
||||||
|
Level: msg.level,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,47 +184,52 @@ func (r *Redirect) Messages() map[string]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message Get flash message by key.
|
// Message Get flash message by key.
|
||||||
func (r *Redirect) Message(key string) string {
|
func (r *Redirect) Message(key string) FlashMessage {
|
||||||
msgs := r.c.redirectionMessages
|
msgs := r.c.flashMessages
|
||||||
|
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
k, v := parseMessage(msg)
|
if msg.key == key && !msg.isOldInput {
|
||||||
|
return FlashMessage{
|
||||||
|
Key: msg.key,
|
||||||
|
Value: msg.value,
|
||||||
|
Level: msg.level,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(k, OldInputDataPrefix) && k == key {
|
return FlashMessage{}
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OldInputs Get old input data.
|
// OldInputs Get old input data.
|
||||||
func (r *Redirect) OldInputs() map[string]string {
|
func (r *Redirect) OldInputs() []OldInputData {
|
||||||
msgs := r.c.redirectionMessages
|
inputs := make([]OldInputData, 0)
|
||||||
oldInputs := make(map[string]string, len(msgs))
|
|
||||||
|
|
||||||
for _, msg := range msgs {
|
for _, msg := range r.c.flashMessages {
|
||||||
k, v := parseMessage(msg)
|
if msg.isOldInput {
|
||||||
|
inputs = append(inputs, OldInputData{
|
||||||
if strings.HasPrefix(k, OldInputDataPrefix) {
|
Key: msg.key,
|
||||||
// remove "old_input_data_" part from key
|
Value: msg.value,
|
||||||
oldInputs[k[len(OldInputDataPrefix):]] = v
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return oldInputs
|
|
||||||
|
return inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
// OldInput Get old input data by key.
|
// OldInput Get old input data by key.
|
||||||
func (r *Redirect) OldInput(key string) string {
|
func (r *Redirect) OldInput(key string) OldInputData {
|
||||||
msgs := r.c.redirectionMessages
|
msgs := r.c.flashMessages
|
||||||
|
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
k, v := parseMessage(msg)
|
if msg.key == key && msg.isOldInput {
|
||||||
|
return OldInputData{
|
||||||
|
Key: msg.key,
|
||||||
|
Value: msg.value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(k, OldInputDataPrefix) && k[len(OldInputDataPrefix):] == key {
|
return OldInputData{}
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To redirect to the URL derived from the specified path, with specified status.
|
// To redirect to the URL derived from the specified path, with specified status.
|
||||||
|
@ -240,66 +295,32 @@ func (r *Redirect) Back(fallback ...string) error {
|
||||||
return r.To(location)
|
return r.To(location)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseAndClearFlashMessages is a method to get flash messages before removing them
|
// parseAndClearFlashMessages is a method to get flash messages before they are getting removed
|
||||||
func (r *Redirect) parseAndClearFlashMessages() {
|
func (r *Redirect) parseAndClearFlashMessages() {
|
||||||
// parse flash messages
|
// parse flash messages
|
||||||
cookieValue := r.c.Cookies(FlashCookieName)
|
cookieValue := r.c.Cookies(FlashCookieName)
|
||||||
|
|
||||||
var commaPos int
|
_, err := r.c.flashMessages.UnmarshalMsg(r.c.app.getBytes(cookieValue))
|
||||||
for {
|
if err != nil {
|
||||||
commaPos = findNextNonEscapedCharsetPosition(cookieValue, []byte(CookieDataSeparator))
|
return
|
||||||
if commaPos == -1 {
|
|
||||||
r.c.redirectionMessages = append(r.c.redirectionMessages, utils.Trim(cookieValue, ' '))
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
r.c.redirectionMessages = append(r.c.redirectionMessages, utils.Trim(cookieValue[:commaPos], ' '))
|
|
||||||
cookieValue = cookieValue[commaPos+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
r.c.ClearCookie(FlashCookieName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// processFlashMessages is a helper function to process flash messages and old input data
|
// processFlashMessages is a helper function to process flash messages and old input data
|
||||||
// and set them as cookies
|
// and set them as cookies
|
||||||
func (r *Redirect) processFlashMessages() {
|
func (r *Redirect) processFlashMessages() {
|
||||||
// Flash messages
|
if len(r.messages) == 0 {
|
||||||
if len(r.messages) > 0 || len(r.oldInput) > 0 {
|
return
|
||||||
messageText := bytebufferpool.Get()
|
}
|
||||||
defer bytebufferpool.Put(messageText)
|
|
||||||
|
|
||||||
// flash messages
|
val, err := r.messages.MarshalMsg(nil)
|
||||||
for i, message := range r.messages {
|
if err != nil {
|
||||||
messageText.WriteString(message)
|
return
|
||||||
// when there are more messages or oldInput -> add a comma
|
|
||||||
if len(r.messages)-1 != i || (len(r.messages)-1 == i && len(r.oldInput) > 0) {
|
|
||||||
messageText.WriteString(CookieDataSeparator)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.messages = r.messages[:0]
|
|
||||||
|
|
||||||
// old input data
|
|
||||||
i := 1
|
|
||||||
for k, v := range r.oldInput {
|
|
||||||
messageText.WriteString(OldInputDataPrefix + k + CookieDataAssigner + v)
|
|
||||||
if len(r.oldInput) != i {
|
|
||||||
messageText.WriteString(CookieDataSeparator)
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.c.Cookie(&Cookie{
|
r.c.Cookie(&Cookie{
|
||||||
Name: FlashCookieName,
|
Name: FlashCookieName,
|
||||||
Value: r.c.app.getString(messageText.Bytes()),
|
Value: r.c.app.getString(val),
|
||||||
SessionOnly: true,
|
SessionOnly: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// parseMessage is a helper function to parse flash messages and old input data
|
|
||||||
func parseMessage(raw string) (string, string) { //nolint: revive // not necessary
|
|
||||||
if i := findNextNonEscapedCharsetPosition(raw, []byte(CookieDataAssigner)); i != -1 {
|
|
||||||
return RemoveEscapeChar(raw[:i]), RemoveEscapeChar(raw[i+1:])
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemoveEscapeChar(raw), ""
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
package fiber
|
||||||
|
|
||||||
|
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tinylib/msgp/msgp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecodeMsg implements msgp.Decodable
|
||||||
|
func (z *redirectionMsg) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
|
var field []byte
|
||||||
|
_ = field
|
||||||
|
var zb0001 uint32
|
||||||
|
zb0001, err = dc.ReadMapHeader()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for zb0001 > 0 {
|
||||||
|
zb0001--
|
||||||
|
field, err = dc.ReadMapKeyPtr()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch msgp.UnsafeString(field) {
|
||||||
|
case "key":
|
||||||
|
z.key, err = dc.ReadString()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "key")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "value":
|
||||||
|
z.value, err = dc.ReadString()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "level":
|
||||||
|
z.level, err = dc.ReadUint8()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "level")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "isOldInput":
|
||||||
|
z.isOldInput, err = dc.ReadBool()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "isOldInput")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = dc.Skip()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeMsg implements msgp.Encodable
|
||||||
|
func (z *redirectionMsg) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
|
// map header, size 4
|
||||||
|
// write "key"
|
||||||
|
err = en.Append(0x84, 0xa3, 0x6b, 0x65, 0x79)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteString(z.key)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "key")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// write "value"
|
||||||
|
err = en.Append(0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteString(z.value)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// write "level"
|
||||||
|
err = en.Append(0xa5, 0x6c, 0x65, 0x76, 0x65, 0x6c)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteUint8(z.level)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "level")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// write "isOldInput"
|
||||||
|
err = en.Append(0xaa, 0x69, 0x73, 0x4f, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteBool(z.isOldInput)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "isOldInput")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalMsg implements msgp.Marshaler
|
||||||
|
func (z *redirectionMsg) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
|
o = msgp.Require(b, z.Msgsize())
|
||||||
|
// map header, size 4
|
||||||
|
// string "key"
|
||||||
|
o = append(o, 0x84, 0xa3, 0x6b, 0x65, 0x79)
|
||||||
|
o = msgp.AppendString(o, z.key)
|
||||||
|
// string "value"
|
||||||
|
o = append(o, 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65)
|
||||||
|
o = msgp.AppendString(o, z.value)
|
||||||
|
// string "level"
|
||||||
|
o = append(o, 0xa5, 0x6c, 0x65, 0x76, 0x65, 0x6c)
|
||||||
|
o = msgp.AppendUint8(o, z.level)
|
||||||
|
// string "isOldInput"
|
||||||
|
o = append(o, 0xaa, 0x69, 0x73, 0x4f, 0x6c, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74)
|
||||||
|
o = msgp.AppendBool(o, z.isOldInput)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalMsg implements msgp.Unmarshaler
|
||||||
|
func (z *redirectionMsg) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
|
var field []byte
|
||||||
|
_ = field
|
||||||
|
var zb0001 uint32
|
||||||
|
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for zb0001 > 0 {
|
||||||
|
zb0001--
|
||||||
|
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch msgp.UnsafeString(field) {
|
||||||
|
case "key":
|
||||||
|
z.key, bts, err = msgp.ReadStringBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "key")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "value":
|
||||||
|
z.value, bts, err = msgp.ReadStringBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "level":
|
||||||
|
z.level, bts, err = msgp.ReadUint8Bytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "level")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "isOldInput":
|
||||||
|
z.isOldInput, bts, err = msgp.ReadBoolBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "isOldInput")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
bts, err = msgp.Skip(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o = bts
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||||
|
func (z *redirectionMsg) Msgsize() (s int) {
|
||||||
|
s = 1 + 4 + msgp.StringPrefixSize + len(z.key) + 6 + msgp.StringPrefixSize + len(z.value) + 6 + msgp.Uint8Size + 11 + msgp.BoolSize
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMsg implements msgp.Decodable
|
||||||
|
func (z *redirectionMsgs) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
|
var zb0002 uint32
|
||||||
|
zb0002, err = dc.ReadArrayHeader()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cap((*z)) >= int(zb0002) {
|
||||||
|
(*z) = (*z)[:zb0002]
|
||||||
|
} else {
|
||||||
|
(*z) = make(redirectionMsgs, zb0002)
|
||||||
|
}
|
||||||
|
for zb0001 := range *z {
|
||||||
|
err = (*z)[zb0001].DecodeMsg(dc)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, zb0001)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeMsg implements msgp.Encodable
|
||||||
|
func (z redirectionMsgs) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
|
err = en.WriteArrayHeader(uint32(len(z)))
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for zb0003 := range z {
|
||||||
|
err = z[zb0003].EncodeMsg(en)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, zb0003)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalMsg implements msgp.Marshaler
|
||||||
|
func (z redirectionMsgs) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
|
o = msgp.Require(b, z.Msgsize())
|
||||||
|
o = msgp.AppendArrayHeader(o, uint32(len(z)))
|
||||||
|
for zb0003 := range z {
|
||||||
|
o, err = z[zb0003].MarshalMsg(o)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, zb0003)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalMsg implements msgp.Unmarshaler
|
||||||
|
func (z *redirectionMsgs) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
|
var zb0002 uint32
|
||||||
|
zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cap((*z)) >= int(zb0002) {
|
||||||
|
(*z) = (*z)[:zb0002]
|
||||||
|
} else {
|
||||||
|
(*z) = make(redirectionMsgs, zb0002)
|
||||||
|
}
|
||||||
|
for zb0001 := range *z {
|
||||||
|
bts, err = (*z)[zb0001].UnmarshalMsg(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, zb0001)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o = bts
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||||
|
func (z redirectionMsgs) Msgsize() (s int) {
|
||||||
|
s = msgp.ArrayHeaderSize
|
||||||
|
for zb0003 := range z {
|
||||||
|
s += z[zb0003].Msgsize()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
package fiber
|
||||||
|
|
||||||
|
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tinylib/msgp/msgp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMarshalUnmarshalredirectionMsg(t *testing.T) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
bts, err := v.MarshalMsg(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
left, err := v.UnmarshalMsg(bts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(left) > 0 {
|
||||||
|
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||||
|
}
|
||||||
|
|
||||||
|
left, err = msgp.Skip(bts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(left) > 0 {
|
||||||
|
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMarshalMsgredirectionMsg(b *testing.B) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.MarshalMsg(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAppendMsgredirectionMsg(b *testing.B) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
bts := make([]byte, 0, v.Msgsize())
|
||||||
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
|
b.SetBytes(int64(len(bts)))
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnmarshalredirectionMsg(b *testing.B) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
bts, _ := v.MarshalMsg(nil)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.SetBytes(int64(len(bts)))
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := v.UnmarshalMsg(bts)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeDecoderedirectionMsg(t *testing.T) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
|
||||||
|
m := v.Msgsize()
|
||||||
|
if buf.Len() > m {
|
||||||
|
t.Log("WARNING: TestEncodeDecoderedirectionMsg Msgsize() is inaccurate")
|
||||||
|
}
|
||||||
|
|
||||||
|
vn := redirectionMsg{}
|
||||||
|
err := msgp.Decode(&buf, &vn)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
err = msgp.NewReader(&buf).Skip()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncoderedirectionMsg(b *testing.B) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
en := msgp.NewWriter(msgp.Nowhere)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.EncodeMsg(en)
|
||||||
|
}
|
||||||
|
en.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecoderedirectionMsg(b *testing.B) {
|
||||||
|
v := redirectionMsg{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||||
|
dc := msgp.NewReader(rd)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
err := v.DecodeMsg(dc)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalUnmarshalredirectionMsgs(t *testing.T) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
bts, err := v.MarshalMsg(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
left, err := v.UnmarshalMsg(bts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(left) > 0 {
|
||||||
|
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||||
|
}
|
||||||
|
|
||||||
|
left, err = msgp.Skip(bts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(left) > 0 {
|
||||||
|
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMarshalMsgredirectionMsgs(b *testing.B) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.MarshalMsg(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAppendMsgredirectionMsgs(b *testing.B) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
bts := make([]byte, 0, v.Msgsize())
|
||||||
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
|
b.SetBytes(int64(len(bts)))
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnmarshalredirectionMsgs(b *testing.B) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
bts, _ := v.MarshalMsg(nil)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.SetBytes(int64(len(bts)))
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := v.UnmarshalMsg(bts)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeDecoderedirectionMsgs(t *testing.T) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
|
||||||
|
m := v.Msgsize()
|
||||||
|
if buf.Len() > m {
|
||||||
|
t.Log("WARNING: TestEncodeDecoderedirectionMsgs Msgsize() is inaccurate")
|
||||||
|
}
|
||||||
|
|
||||||
|
vn := redirectionMsgs{}
|
||||||
|
err := msgp.Decode(&buf, &vn)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
err = msgp.NewReader(&buf).Skip()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncoderedirectionMsgs(b *testing.B) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
en := msgp.NewWriter(msgp.Nowhere)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.EncodeMsg(en)
|
||||||
|
}
|
||||||
|
en.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecoderedirectionMsgs(b *testing.B) {
|
||||||
|
v := redirectionMsgs{}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
msgp.Encode(&buf, &v)
|
||||||
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||||
|
dc := msgp.NewReader(rd)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
err := v.DecodeMsg(dc)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
444
redirect_test.go
444
redirect_test.go
|
@ -5,16 +5,13 @@
|
||||||
package fiber
|
package fiber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"bytes"
|
||||||
"net"
|
"mime/multipart"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
"github.com/valyala/fasthttp/fasthttputil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// go test -run Test_Redirect_To
|
// go test -run Test_Redirect_To
|
||||||
|
@ -40,16 +37,20 @@ func Test_Redirect_To_WithFlashMessages(t *testing.T) {
|
||||||
app := New()
|
app := New()
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||||
|
|
||||||
err := c.Redirect().With("success", "1").With("message", "test").To("http://example.com")
|
err := c.Redirect().With("success", "2").With("success", "1").With("message", "test", 2).To("http://example.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 302, c.Response().StatusCode())
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
require.Equal(t, "http://example.com", string(c.Response().Header.Peek(HeaderLocation)))
|
require.Equal(t, "http://example.com", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
equal := c.GetRespHeader(HeaderSetCookie) == "fiber_flash=success:1,message:test; path=/; SameSite=Lax" || c.GetRespHeader(HeaderSetCookie) == "fiber_flash=message:test,success:1; path=/; SameSite=Lax"
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
require.True(t, equal)
|
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
var msgs redirectionMsgs
|
||||||
require.Equal(t, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, msgs, 2)
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 2, isOldInput: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -run Test_Redirect_Route_WithParams
|
// go test -run Test_Redirect_Route_WithParams
|
||||||
|
@ -88,6 +89,7 @@ func Test_Redirect_Route_WithParams_WithQueries(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 302, c.Response().StatusCode())
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
|
|
||||||
// analysis of query parameters with url parsing, since a map pass is always randomly ordered
|
// analysis of query parameters with url parsing, since a map pass is always randomly ordered
|
||||||
location, err := url.Parse(string(c.Response().Header.Peek(HeaderLocation)))
|
location, err := url.Parse(string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
require.NoError(t, err, "url.Parse(location)")
|
require.NoError(t, err, "url.Parse(location)")
|
||||||
|
@ -183,11 +185,15 @@ func Test_Redirect_Back_WithFlashMessages(t *testing.T) {
|
||||||
require.Equal(t, 302, c.Response().StatusCode())
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
require.Equal(t, "/", string(c.Response().Header.Peek(HeaderLocation)))
|
require.Equal(t, "/", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
equal := c.GetRespHeader(HeaderSetCookie) == "fiber_flash=success:1,message:test; path=/; SameSite=Lax" || c.GetRespHeader(HeaderSetCookie) == "fiber_flash=message:test,success:1; path=/; SameSite=Lax"
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
require.True(t, equal)
|
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
var msgs redirectionMsgs
|
||||||
require.Equal(t, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, msgs, 2)
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -run Test_Redirect_Back_WithReferer
|
// go test -run Test_Redirect_Back_WithReferer
|
||||||
|
@ -222,21 +228,32 @@ func Test_Redirect_Route_WithFlashMessages(t *testing.T) {
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
err := c.Redirect().With("success", "1").With("message", "test").Route("user")
|
err := c.Redirect().With("success", "1").With("message", "test").Route("user")
|
||||||
|
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 302, c.Response().StatusCode())
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
equal := c.GetRespHeader(HeaderSetCookie) == "fiber_flash=success:1,message:test; path=/; SameSite=Lax" || c.GetRespHeader(HeaderSetCookie) == "fiber_flash=message:test,success:1; path=/; SameSite=Lax"
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
require.True(t, equal)
|
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
var msgs redirectionMsgs
|
||||||
require.Equal(t, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, msgs, 2)
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -run Test_Redirect_Route_WithOldInput
|
// go test -run Test_Redirect_Route_WithOldInput
|
||||||
func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("Query", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
app := New()
|
app := New()
|
||||||
app.Get("/user", func(c Ctx) error {
|
app.Get("/user", func(c Ctx) error {
|
||||||
return c.SendString("user")
|
return c.SendString("user")
|
||||||
|
@ -246,19 +263,108 @@ func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
||||||
|
|
||||||
c.Request().URI().SetQueryString("id=1&name=tom")
|
c.Request().URI().SetQueryString("id=1&name=tom")
|
||||||
err := c.Redirect().With("success", "1").With("message", "test").WithInput().Route("user")
|
err := c.Redirect().With("success", "1").With("message", "test").WithInput().Route("user")
|
||||||
|
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "id", value: "1", isOldInput: true})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "name", value: "tom", isOldInput: true})
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 302, c.Response().StatusCode())
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
require.Contains(t, c.GetRespHeader(HeaderSetCookie), "fiber_flash=")
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
require.Contains(t, c.GetRespHeader(HeaderSetCookie), "success:1")
|
|
||||||
require.Contains(t, c.GetRespHeader(HeaderSetCookie), "message:test")
|
|
||||||
|
|
||||||
require.Contains(t, c.GetRespHeader(HeaderSetCookie), ",old_input_data_id:1")
|
var msgs redirectionMsgs
|
||||||
require.Contains(t, c.GetRespHeader(HeaderSetCookie), ",old_input_data_name:tom")
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
require.Len(t, msgs, 4)
|
||||||
require.Equal(t, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "id", value: "1", level: 0, isOldInput: true})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "name", value: "tom", level: 0, isOldInput: true})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Form", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
app := New()
|
||||||
|
app.Post("/user", func(c Ctx) error {
|
||||||
|
return c.SendString("user")
|
||||||
|
}).Name("user")
|
||||||
|
|
||||||
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderContentType, MIMEApplicationForm)
|
||||||
|
c.Request().SetBodyString("id=1&name=tom")
|
||||||
|
err := c.Redirect().With("success", "1").With("message", "test").WithInput().Route("user")
|
||||||
|
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "id", value: "1", isOldInput: true})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "name", value: "tom", isOldInput: true})
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
|
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
|
|
||||||
|
var msgs redirectionMsgs
|
||||||
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, msgs, 4)
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "id", value: "1", level: 0, isOldInput: true})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "name", value: "tom", level: 0, isOldInput: true})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("MultipartForm", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
app := New()
|
||||||
|
app.Get("/user", func(c Ctx) error {
|
||||||
|
return c.SendString("user")
|
||||||
|
}).Name("user")
|
||||||
|
|
||||||
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
|
body := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
|
||||||
|
require.NoError(t, writer.WriteField("id", "1"))
|
||||||
|
require.NoError(t, writer.WriteField("name", "tom"))
|
||||||
|
require.NoError(t, writer.Close())
|
||||||
|
|
||||||
|
c.Request().SetBody(body.Bytes())
|
||||||
|
c.Request().Header.Set(HeaderContentType, writer.FormDataContentType())
|
||||||
|
|
||||||
|
err := c.Redirect().With("success", "1").With("message", "test").WithInput().Route("user")
|
||||||
|
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "id", value: "1", isOldInput: true})
|
||||||
|
require.Contains(t, c.redirect.messages, redirectionMsg{key: "name", value: "tom", isOldInput: true})
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 302, c.Response().StatusCode())
|
||||||
|
require.Equal(t, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
|
|
||||||
|
var msgs redirectionMsgs
|
||||||
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, msgs, 4)
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "id", value: "1", level: 0, isOldInput: true})
|
||||||
|
require.Contains(t, msgs, redirectionMsg{key: "name", value: "tom", level: 0, isOldInput: true})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -run Test_Redirect_parseAndClearFlashMessages
|
// go test -run Test_Redirect_parseAndClearFlashMessages
|
||||||
|
@ -272,105 +378,83 @@ func Test_Redirect_parseAndClearFlashMessages(t *testing.T) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
msgs := redirectionMsgs{
|
||||||
|
{
|
||||||
|
key: "success",
|
||||||
|
value: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "message",
|
||||||
|
value: "test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
value: "tom",
|
||||||
|
isOldInput: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "id",
|
||||||
|
value: "1",
|
||||||
|
isOldInput: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := msgs.MarshalMsg(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
|
|
||||||
require.Equal(t, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Equal(t, FlashMessage{
|
||||||
|
Key: "success",
|
||||||
|
Value: "1",
|
||||||
|
Level: 0,
|
||||||
|
}, c.Redirect().Message("success"))
|
||||||
|
|
||||||
require.Equal(t, "1", c.Redirect().Message("success"))
|
require.Equal(t, FlashMessage{
|
||||||
require.Equal(t, "test", c.Redirect().Message("message"))
|
Key: "message",
|
||||||
require.Equal(t, map[string]string{"success": "1", "message": "test"}, c.Redirect().Messages())
|
Value: "test",
|
||||||
|
Level: 0,
|
||||||
|
}, c.Redirect().Message("message"))
|
||||||
|
|
||||||
require.Equal(t, "1", c.Redirect().OldInput("id"))
|
require.Equal(t, FlashMessage{}, c.Redirect().Message("not_message"))
|
||||||
require.Equal(t, "tom", c.Redirect().OldInput("name"))
|
|
||||||
require.Equal(t, map[string]string{"id": "1", "name": "tom"}, c.Redirect().OldInputs())
|
|
||||||
}
|
|
||||||
|
|
||||||
// go test -run Test_Redirect_Request
|
require.Equal(t, []FlashMessage{
|
||||||
func Test_Redirect_Request(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
app := New()
|
|
||||||
|
|
||||||
app.Get("/", func(c Ctx) error {
|
|
||||||
return c.Redirect().With("key", "value").With("key2", "value2").With("co\\:m\\,ma", "Fi\\:ber\\, v3").Route("name")
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("/with-inputs", func(c Ctx) error {
|
|
||||||
return c.Redirect().WithInput().With("key", "value").With("key2", "value2").Route("name")
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("/just-inputs", func(c Ctx) error {
|
|
||||||
return c.Redirect().WithInput().Route("name")
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("/redirected", func(c Ctx) error {
|
|
||||||
return c.JSON(Map{
|
|
||||||
"messages": c.Redirect().Messages(),
|
|
||||||
"inputs": c.Redirect().OldInputs(),
|
|
||||||
})
|
|
||||||
}).Name("name")
|
|
||||||
|
|
||||||
// Start test server
|
|
||||||
ln := fasthttputil.NewInmemoryListener()
|
|
||||||
go func() {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 250*time.Millisecond)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := app.Listener(ln, ListenConfig{
|
|
||||||
DisableStartupMessage: true,
|
|
||||||
GracefulContext: ctx,
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Test cases
|
|
||||||
testCases := []struct {
|
|
||||||
ExpectedErr error
|
|
||||||
URL string
|
|
||||||
CookieValue string
|
|
||||||
ExpectedBody string
|
|
||||||
ExpectedStatusCode int
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
URL: "/",
|
Key: "success",
|
||||||
CookieValue: "key:value,key2:value2,co\\:m\\,ma:Fi\\:ber\\, v3",
|
Value: "1",
|
||||||
ExpectedBody: `{"inputs":{},"messages":{"co:m,ma":"Fi:ber, v3","key":"value","key2":"value2"}}`,
|
Level: 0,
|
||||||
ExpectedStatusCode: StatusOK,
|
|
||||||
ExpectedErr: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
URL: "/with-inputs?name=john&surname=doe",
|
Key: "message",
|
||||||
CookieValue: "key:value,key2:value2,key:value,key2:value2,old_input_data_name:john,old_input_data_surname:doe",
|
Value: "test",
|
||||||
ExpectedBody: `{"inputs":{"name":"john","surname":"doe"},"messages":{"key":"value","key2":"value2"}}`,
|
Level: 0,
|
||||||
ExpectedStatusCode: StatusOK,
|
},
|
||||||
ExpectedErr: nil,
|
}, c.Redirect().Messages())
|
||||||
|
|
||||||
|
require.Equal(t, OldInputData{
|
||||||
|
Key: "id",
|
||||||
|
Value: "1",
|
||||||
|
}, c.Redirect().OldInput("id"))
|
||||||
|
|
||||||
|
require.Equal(t, OldInputData{
|
||||||
|
Key: "name",
|
||||||
|
Value: "tom",
|
||||||
|
}, c.Redirect().OldInput("name"))
|
||||||
|
|
||||||
|
require.Equal(t, OldInputData{}, c.Redirect().OldInput("not_name"))
|
||||||
|
|
||||||
|
require.Equal(t, []OldInputData{
|
||||||
|
{
|
||||||
|
Key: "name",
|
||||||
|
Value: "tom",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
URL: "/just-inputs?name=john&surname=doe",
|
Key: "id",
|
||||||
CookieValue: "old_input_data_name:john,old_input_data_surname:doe",
|
Value: "1",
|
||||||
ExpectedBody: `{"inputs":{"name":"john","surname":"doe"},"messages":{}}`,
|
|
||||||
ExpectedStatusCode: StatusOK,
|
|
||||||
ExpectedErr: nil,
|
|
||||||
},
|
},
|
||||||
}
|
}, c.Redirect().OldInputs())
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
client := &fasthttp.HostClient{
|
|
||||||
Dial: func(_ string) (net.Conn, error) {
|
|
||||||
return ln.Dial()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse()
|
|
||||||
req.SetRequestURI("http://example.com" + tc.URL)
|
|
||||||
req.Header.SetCookie(FlashCookieName, tc.CookieValue)
|
|
||||||
err := client.DoRedirects(req, resp, 1)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, tc.ExpectedBody, string(resp.Body()))
|
|
||||||
require.Equal(t, tc.ExpectedStatusCode, resp.StatusCode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_Route -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_Route -benchmem -count=4
|
||||||
|
@ -454,11 +538,35 @@ func Benchmark_Redirect_Route_WithFlashMessages(b *testing.B) {
|
||||||
require.Equal(b, 302, c.Response().StatusCode())
|
require.Equal(b, 302, c.Response().StatusCode())
|
||||||
require.Equal(b, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
require.Equal(b, "/user", string(c.Response().Header.Peek(HeaderLocation)))
|
||||||
|
|
||||||
equal := c.GetRespHeader(HeaderSetCookie) == "fiber_flash=success:1,message:test; path=/; SameSite=Lax" || c.GetRespHeader(HeaderSetCookie) == "fiber_flash=message:test,success:1; path=/; SameSite=Lax"
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
require.True(b, equal)
|
|
||||||
|
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
var msgs redirectionMsgs
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
_, err = msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
require.Contains(b, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(b, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
var testredirectionMsgs = redirectionMsgs{
|
||||||
|
{
|
||||||
|
key: "success",
|
||||||
|
value: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "message",
|
||||||
|
value: "test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
value: "tom",
|
||||||
|
isOldInput: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "id",
|
||||||
|
value: "1",
|
||||||
|
isOldInput: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_parseAndClearFlashMessages -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_parseAndClearFlashMessages -benchmem -count=4
|
||||||
|
@ -470,7 +578,10 @@ func Benchmark_Redirect_parseAndClearFlashMessages(b *testing.B) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -479,15 +590,25 @@ func Benchmark_Redirect_parseAndClearFlashMessages(b *testing.B) {
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Equal(b, FlashMessage{
|
||||||
|
Key: "success",
|
||||||
|
Value: "1",
|
||||||
|
}, c.Redirect().Message("success"))
|
||||||
|
|
||||||
require.Equal(b, "1", c.Redirect().Message("success"))
|
require.Equal(b, FlashMessage{
|
||||||
require.Equal(b, "test", c.Redirect().Message("message"))
|
Key: "message",
|
||||||
require.Equal(b, map[string]string{"success": "1", "message": "test"}, c.Redirect().Messages())
|
Value: "test",
|
||||||
|
}, c.Redirect().Message("message"))
|
||||||
|
|
||||||
require.Equal(b, "1", c.Redirect().OldInput("id"))
|
require.Equal(b, OldInputData{
|
||||||
require.Equal(b, "tom", c.Redirect().OldInput("name"))
|
Key: "id",
|
||||||
require.Equal(b, map[string]string{"id": "1", "name": "tom"}, c.Redirect().OldInputs())
|
Value: "1",
|
||||||
|
}, c.Redirect().OldInput("id"))
|
||||||
|
|
||||||
|
require.Equal(b, OldInputData{
|
||||||
|
Key: "name",
|
||||||
|
Value: "tom",
|
||||||
|
}, c.Redirect().OldInput("name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_processFlashMessages -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_processFlashMessages -benchmem -count=4
|
||||||
|
@ -508,7 +629,15 @@ func Benchmark_Redirect_processFlashMessages(b *testing.B) {
|
||||||
c.Redirect().processFlashMessages()
|
c.Redirect().processFlashMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=success:1,message:test; path=/; SameSite=Lax", c.GetRespHeader(HeaderSetCookie))
|
c.Context().Request.Header.Set(HeaderCookie, c.GetRespHeader(HeaderSetCookie)) // necessary for testing
|
||||||
|
|
||||||
|
var msgs redirectionMsgs
|
||||||
|
_, err := msgs.UnmarshalMsg([]byte(c.Cookies(FlashCookieName)))
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
require.Len(b, msgs, 2)
|
||||||
|
require.Contains(b, msgs, redirectionMsg{key: "success", value: "1", level: 0, isOldInput: false})
|
||||||
|
require.Contains(b, msgs, redirectionMsg{key: "message", value: "test", level: 0, isOldInput: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_Messages -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_Messages -benchmem -count=4
|
||||||
|
@ -520,10 +649,13 @@ func Benchmark_Redirect_Messages(b *testing.B) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
|
|
||||||
var msgs map[string]string
|
var msgs []FlashMessage
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -532,8 +664,17 @@ func Benchmark_Redirect_Messages(b *testing.B) {
|
||||||
msgs = c.Redirect().Messages()
|
msgs = c.Redirect().Messages()
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Contains(b, msgs, FlashMessage{
|
||||||
require.Equal(b, map[string]string{"success": "1", "message": "test"}, msgs)
|
Key: "success",
|
||||||
|
Value: "1",
|
||||||
|
Level: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Contains(b, msgs, FlashMessage{
|
||||||
|
Key: "message",
|
||||||
|
Value: "test",
|
||||||
|
Level: 0,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_OldInputs -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_OldInputs -benchmem -count=4
|
||||||
|
@ -545,10 +686,13 @@ func Benchmark_Redirect_OldInputs(b *testing.B) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
|
|
||||||
var oldInputs map[string]string
|
var oldInputs []OldInputData
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -557,8 +701,15 @@ func Benchmark_Redirect_OldInputs(b *testing.B) {
|
||||||
oldInputs = c.Redirect().OldInputs()
|
oldInputs = c.Redirect().OldInputs()
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Contains(b, oldInputs, OldInputData{
|
||||||
require.Equal(b, map[string]string{"id": "1", "name": "tom"}, oldInputs)
|
Key: "name",
|
||||||
|
Value: "tom",
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Contains(b, oldInputs, OldInputData{
|
||||||
|
Key: "id",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_Message -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_Message -benchmem -count=4
|
||||||
|
@ -570,10 +721,13 @@ func Benchmark_Redirect_Message(b *testing.B) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
|
|
||||||
var msg string
|
var msg FlashMessage
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -582,8 +736,11 @@ func Benchmark_Redirect_Message(b *testing.B) {
|
||||||
msg = c.Redirect().Message("message")
|
msg = c.Redirect().Message("message")
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Equal(b, FlashMessage{
|
||||||
require.Equal(b, "test", msg)
|
Key: "message",
|
||||||
|
Value: "test",
|
||||||
|
Level: 0,
|
||||||
|
}, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// go test -v -run=^$ -bench=Benchmark_Redirect_OldInput -benchmem -count=4
|
// go test -v -run=^$ -bench=Benchmark_Redirect_OldInput -benchmem -count=4
|
||||||
|
@ -595,10 +752,13 @@ func Benchmark_Redirect_OldInput(b *testing.B) {
|
||||||
|
|
||||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||||
|
|
||||||
c.Request().Header.Set(HeaderCookie, "fiber_flash=success:1,message:test,old_input_data_name:tom,old_input_data_id:1")
|
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
c.Request().Header.Set(HeaderCookie, "fiber_flash="+string(val))
|
||||||
c.Redirect().parseAndClearFlashMessages()
|
c.Redirect().parseAndClearFlashMessages()
|
||||||
|
|
||||||
var input string
|
var input OldInputData
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -607,6 +767,8 @@ func Benchmark_Redirect_OldInput(b *testing.B) {
|
||||||
input = c.Redirect().OldInput("name")
|
input = c.Redirect().OldInput("name")
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(b, "fiber_flash=; expires=Tue, 10 Nov 2009 23:00:00 GMT", c.GetRespHeader(HeaderSetCookie))
|
require.Equal(b, OldInputData{
|
||||||
require.Equal(b, "tom", input)
|
Key: "name",
|
||||||
|
Value: "tom",
|
||||||
|
}, input)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue