From 1e8b533d45ad6c810d9a569625c1938aaa1d013d Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sun, 8 Nov 2020 18:36:25 +0530 Subject: [PATCH] Fix echo's URI routing race condition that caused random 404s. --- cmd/campaigns.go | 6 +++--- cmd/handlers.go | 20 ++++++++++++++++++++ cmd/lists.go | 6 +++--- cmd/templates.go | 6 +++--- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/cmd/campaigns.go b/cmd/campaigns.go index 55d9742..b3b66be 100644 --- a/cmd/campaigns.go +++ b/cmd/campaigns.go @@ -267,9 +267,9 @@ func handleCreateCampaign(c echo.Context) error { } // Hand over to the GET handler to return the last insertion. - c.SetParamNames("id") - c.SetParamValues(fmt.Sprintf("%d", newID)) - return handleGetCampaigns(c) + return handleGetCampaigns(copyEchoCtx(c, map[string]string{ + "id": fmt.Sprintf("%d", newID), + })) } // handleUpdateCampaign handles campaign modification. diff --git a/cmd/handlers.go b/cmd/handlers.go index e46dd9e..b699854 100644 --- a/cmd/handlers.go +++ b/cmd/handlers.go @@ -238,3 +238,23 @@ func getPagination(q url.Values, perPage, maxPerPage int) pagination { Limit: perPage, } } + +// copyEchoCtx returns a copy of the the current echo.Context in a request +// with the given params set for the active handler to proxy the request +// to another handler without mutating its context. +func copyEchoCtx(c echo.Context, params map[string]string) echo.Context { + var ( + keys = make([]string, 0, len(params)) + vals = make([]string, 0, len(params)) + ) + for k, v := range params { + keys = append(keys, k) + vals = append(vals, v) + } + + b := c.Echo().NewContext(c.Request(), c.Response()) + b.Set("app", c.Get("app").(*App)) + b.SetParamNames(keys...) + b.SetParamValues(vals...) + return b +} diff --git a/cmd/lists.go b/cmd/lists.go index ad5639d..9c3c20a 100644 --- a/cmd/lists.go +++ b/cmd/lists.go @@ -118,9 +118,9 @@ func handleCreateList(c echo.Context) error { } // Hand over to the GET handler to return the last insertion. - c.SetParamNames("id") - c.SetParamValues(fmt.Sprintf("%d", newID)) - return handleGetLists(c) + return handleGetLists(copyEchoCtx(c, map[string]string{ + "id": fmt.Sprintf("%d", newID), + })) } // handleUpdateList handles list modification. diff --git a/cmd/templates.go b/cmd/templates.go index c0b24b9..b31aa27 100644 --- a/cmd/templates.go +++ b/cmd/templates.go @@ -147,9 +147,9 @@ func handleCreateTemplate(c echo.Context) error { } // Hand over to the GET handler to return the last insertion. - c.SetParamNames("id") - c.SetParamValues(fmt.Sprintf("%d", newID)) - return handleGetTemplates(c) + return handleGetTemplates(copyEchoCtx(c, map[string]string{ + "id": fmt.Sprintf("%d", newID), + })) } // handleUpdateTemplate handles template modification.