Skip to content

Commit

Permalink
Add example for #1706 (we already cover that functionality through th…
Browse files Browse the repository at this point in the history
…e rest of the examples, but make it clear for newcomers that, dependencies can be used for that kind of reasons as well)
  • Loading branch information
kataras committed Jan 21, 2021
1 parent e990b23 commit 6c823e4
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 33 deletions.
1 change: 1 addition & 0 deletions _examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
77 changes: 77 additions & 0 deletions _examples/mvc/request-default-values/main.go
Original file line number Diff line number Diff line change
@@ -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)
}
58 changes: 25 additions & 33 deletions core/host/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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}

Expand Down

0 comments on commit 6c823e4

Please sign in to comment.