From 2cdbe17bd5e7c59af509bf419daaccbe73751f48 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 2 Feb 2019 04:49:58 +0200 Subject: [PATCH] add Context#ResetRequest and core/handlerconv.FromStdWithNext updates the request for any incoming request changes - https://github.com/kataras/iris/issues/1180 Former-commit-id: 764bf26bcaa3b7bdae0a2bdbf3bf2b6f8c5c546e --- context/context.go | 27 +++++++++++++++++++++++++++ core/handlerconv/from_std.go | 1 + core/handlerconv/from_std_test.go | 6 ++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/context/context.go b/context/context.go index 7fa1a95e..fced0607 100644 --- a/context/context.go +++ b/context/context.go @@ -114,6 +114,18 @@ type Context interface { // Request returns the original *http.Request, as expected. Request() *http.Request + // ResetRequest sets the Context's Request, + // It is useful to store the new request created by a std *http.Request#WithContext() into Iris' Context. + // Use `ResetRequest` when for some reason you want to make a full + // override of the *http.Request. + // Note that: when you just want to change one of each fields you can use the Request() which returns a pointer to Request, + // so the changes will have affect without a full override. + // Usage: you use a native http handler which uses the standard "context" package + // to get values instead of the Iris' Context#Values(): + // r := c.Request() + // stdCtx := context.WithValue(r.Context(), key, val) + // ctx.ResetRequest(r.WithContext(stdCtx)). + ResetRequest(r *http.Request) // SetCurrentRouteName sets the route's name internally, // in order to be able to find the correct current "read-only" Route when @@ -1068,6 +1080,21 @@ func (ctx *context) Request() *http.Request { return ctx.request } +// ResetRequest sets the Context's Request, +// It is useful to store the new request created by a std *http.Request#WithContext() into Iris' Context. +// Use `ResetRequest` when for some reason you want to make a full +// override of the *http.Request. +// Note that: when you just want to change one of each fields you can use the Request() which returns a pointer to Request, +// so the changes will have affect without a full override. +// Usage: you use a native http handler which uses the standard "context" package +// to get values instead of the Iris' Context#Values(): +// r := c.Request() +// stdCtx := context.WithValue(r.Context(), key, val) +// ctx.ResetRequest(r.WithContext(stdCtx)). +func (ctx *context) ResetRequest(r *http.Request) { + ctx.request = r +} + // SetCurrentRouteName sets the route's name internally, // in order to be able to find the correct current "read-only" Route when // end-developer calls the `GetCurrentRoute()` function. diff --git a/core/handlerconv/from_std.go b/core/handlerconv/from_std.go index 98c22deb..255bcaa9 100644 --- a/core/handlerconv/from_std.go +++ b/core/handlerconv/from_std.go @@ -75,6 +75,7 @@ func FromStd(handler interface{}) context.Handler { func FromStdWithNext(h func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)) context.Handler { return func(ctx context.Context) { next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx.ResetRequest(r) ctx.Next() }) diff --git a/core/handlerconv/from_std_test.go b/core/handlerconv/from_std_test.go index 17f5adcb..49bb7938 100644 --- a/core/handlerconv/from_std_test.go +++ b/core/handlerconv/from_std_test.go @@ -2,6 +2,7 @@ package handlerconv_test import ( + stdContext "context" "net/http" "testing" @@ -42,7 +43,8 @@ func TestFromStdWithNext(t *testing.T) { stdWNext := func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { if username, password, ok := r.BasicAuth(); ok && username == basicauth && password == basicauth { - next.ServeHTTP(w, r) + ctx := stdContext.WithValue(r.Context(), "key", "ok") + next.ServeHTTP(w, r.WithContext(ctx)) return } w.WriteHeader(iris.StatusForbidden) @@ -50,7 +52,7 @@ func TestFromStdWithNext(t *testing.T) { h := handlerconv.FromStdWithNext(stdWNext) next := func(ctx context.Context) { - ctx.WriteString(passed) + ctx.WriteString(ctx.Request().Context().Value("key").(string)) } app := iris.New()