From 6c823e4864245481d12e97ac60eb1ab3ec9c1db4 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Thu, 21 Jan 2021 05:57:37 +0200 Subject: [PATCH] Add example for #1706 (we already cover that functionality through the rest of the examples, but make it clear for newcomers that, dependencies can be used for that kind of reasons as well) --- _examples/README.md | 1 + _examples/mvc/request-default-values/main.go | 77 ++++++++++++++++++++ core/host/proxy.go | 58 +++++++-------- 3 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 _examples/mvc/request-default-values/main.go diff --git a/_examples/README.md b/_examples/README.md index 8cac0ad2..d5c14c8b 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -253,6 +253,7 @@ * [Hello world](mvc/hello-world/main.go) * [Basic](mvc/basic/main.go) * [Wildcard](mvc/basic/wildcard/main.go) + * [Default request values](mvc/request-default-values/main.go) * [Singleton](mvc/singleton) * [Regexp](mvc/regexp/main.go) * [Session Controller](mvc/session-controller/main.go) diff --git a/_examples/mvc/request-default-values/main.go b/_examples/mvc/request-default-values/main.go new file mode 100644 index 00000000..90de0cc7 --- /dev/null +++ b/_examples/mvc/request-default-values/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +// https://github.com/kataras/iris/issues/1706 +// When you need that type of logic behind a request input, +// e.g. set default values, the right way to do that is +// to register a request-scoped dependency for that type. +// We have the `Context.ReadQuery(pointer)` +// which you can use to bind a struct value, that value can have default values. +// Here is how you could do that: +func main() { + app := iris.New() + + mvcApp := mvc.New(app) + { + mvcApp.Register(paramsDependency) + + mvcApp.Handle(new(controller)) + } + + // http://localhost:8080/records?phone=random&order_by=DESC + // http://localhost:8080/records?phone=random + app.Listen(":8080") +} + +type params struct { + CallID string `url:"phone"` + ComDir int `url:"dir"` + CaseUserID string `url:"on"` + StartYear int `url:"sy"` + EndYear int `url:"ey"` + OrderBy string `url:"order_by"` + Offset int `url:"offset"` +} + +// As we've read in the previous examples, the paramsDependency +// describes a request-scoped dependency. +// It should accept the iris context (or any previously registered or builtin dependency) +// and it should return the value which will be binded to the +// controller's methods (or fields) - see `GetRecords`. +var paramsDependency = func(ctx iris.Context) params { + p := params{ + OrderBy: "ASC", // default value. + } + // Bind the URL values to the "p": + ctx.ReadQuery(&p) + // Or bind a specific URL value by giving a default value: + // p.OrderBy = ctx.URLParamDefault("order_by", "ASC") + // + // OR make checks for default values after ReadXXX, + // e.g. if p.OrderBy == "" {...} + + /* More options to read a request: + // Bind the JSON request body to the "p": + ctx.ReadJSON(&p) + // Bind the Form to the "p": + ctx.ReadForm(&p) + // Bind any, based on the client's content-type header: + ctx.ReadBody(&p) + // Bind the http requests to a struct value: + ctx.ReadHeader(&h) + */ + + return p +} + +type controller struct{} + +func (c *controller) GetRecords(stru params) string { + return fmt.Sprintf("%#+v\n", stru) +} diff --git a/core/host/proxy.go b/core/host/proxy.go index 25fa9cbc..85db9f94 100644 --- a/core/host/proxy.go +++ b/core/host/proxy.go @@ -17,26 +17,14 @@ import ( // the target request will be for /base/dir. // // Relative to httputil.NewSingleHostReverseProxy with some additions. +// +// Look `ProxyHandlerRemote` too. func ProxyHandler(target *url.URL) *httputil.ReverseProxy { - targetQuery := target.RawQuery director := func(req *http.Request) { - req.URL.Scheme = target.Scheme - req.URL.Host = target.Host - req.Host = target.Host - + modifyProxiedRequest(req, target) req.URL.Path = path.Join(target.Path, req.URL.Path) - - if targetQuery == "" || req.URL.RawQuery == "" { - req.URL.RawQuery = targetQuery + req.URL.RawQuery - } else { - req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery - } - - if _, ok := req.Header["User-Agent"]; !ok { - // explicitly disable User-Agent so it's not set to default value - req.Header.Set("User-Agent", "") - } } + p := &httputil.ReverseProxy{Director: director} if netutil.IsLoopbackHost(target.Host) { @@ -49,37 +37,41 @@ func ProxyHandler(target *url.URL) *httputil.ReverseProxy { return p } +func modifyProxiedRequest(req *http.Request, target *url.URL) { + req.URL.Scheme = target.Scheme + req.URL.Host = target.Host + req.Host = target.Host + + if target.RawQuery == "" || req.URL.RawQuery == "" { + req.URL.RawQuery = target.RawQuery + req.URL.RawQuery + } else { + req.URL.RawQuery = target.RawQuery + "&" + req.URL.RawQuery + } + + if _, ok := req.Header["User-Agent"]; !ok { + // explicitly disable User-Agent so it's not set to default value + req.Header.Set("User-Agent", "") + } +} + // ProxyHandlerRemote returns a new ReverseProxy that rewrites // URLs to the scheme, host, and path provided in target. // Case 1: req.Host == target.Host // behavior same as ProxyHandler // Case 2: req.Host != target.Host // the target request will be forwarded to the target's url -// insecureSkipVerify indicates enable ssl certificate verification or not +// insecureSkipVerify indicates enable ssl certificate verification or not. +// +// Look `ProxyHandler` too. func ProxyHandlerRemote(target *url.URL, insecureSkipVerify bool) *httputil.ReverseProxy { - targetQuery := target.RawQuery director := func(req *http.Request) { - req.URL.Scheme = target.Scheme + modifyProxiedRequest(req, target) if req.Host != target.Host { req.URL.Path = target.Path } else { req.URL.Path = path.Join(target.Path, req.URL.Path) } - - req.URL.Host = target.Host - req.Host = target.Host - - if targetQuery == "" || req.URL.RawQuery == "" { - req.URL.RawQuery = targetQuery + req.URL.RawQuery - } else { - req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery - } - - if _, ok := req.Header["User-Agent"]; !ok { - // explicitly disable User-Agent so it's not set to default value - req.Header.Set("User-Agent", "") - } } p := &httputil.ReverseProxy{Director: director}