Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After replay attack check Need to forward the request to another server #1181

Closed
Wall-ee opened this issue Feb 2, 2019 · 3 comments

Comments

@Wall-ee
Copy link

commented Feb 2, 2019

hello,every one.
I'm a fresh man of iris user.
recently, we want to use iris as a api gatway to host our SaaS service.
IRIS need to check the Auth and use the information in Http Header to pervent reply attack.

after check the auth and security check, Is there any methods to forward the request to another worker server?
This could be called as a reverse proxy in Nginx.

The link below showed a proxy example. but hot to use it in the ctx context ?
Documentation for the Iris project can be found at
https://stackoverflow.com/questions/41143044/golang-reverseproxy-with-iris-go-framework

app.Post("/", func(ctx iris.Context){
     check auth and security

      forward (reverse proxy )the request here 
}
@kataras

This comment has been minimized.

Copy link
Owner

commented Feb 2, 2019

Hello @Wall-ee ,

So you want dynamically "forward the request" based on an "X-Forward-To" header, the response may be acquired by any external http server that header defines, right?

So, what you can do for start is simple: use an http client (net/http comes with http.Client out of the box), fire a new request to the ctx.GetHeader("X-Forward-To") based on the ctx.Method()(use the http.Client#Do(http.NewRequest(method,...))) -- optionally you can set things like known hosts at least or limit on how much time the client waits for a response from the external server, get the response body back, read the body as []byte, put them in your server's handler(ctx.Write(body)), get the response headers, loop through them(they are just map) and pass them down to your server's handler as well(ctx.Header(key, value)), do the same for the status code, code := resp.StatusCode should go into ctx.StatusCode(code) and so on.

If I don't understand correctly, please give us more information, thank you a lot!

@kataras kataras added the question label Feb 2, 2019

@Wall-ee

This comment has been minimized.

Copy link
Author

commented Feb 13, 2019

i see. so, is there any method in iris to forward the http request instead of using "net/http" package?

@kataras

This comment has been minimized.

Copy link
Owner

commented Aug 14, 2019

We have Proxy and NewRedirection as well, check more at:

iris/core/host/proxy.go

Lines 26 to 113 in eba6adb

// ProxyHandler returns a new ReverseProxy that rewrites
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
//
// Relative to httputil.NewSingleHostReverseProxy with some additions.
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
req.URL.Path = singleJoiningSlash(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) {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
p.Transport = transport
}
return p
}
// NewProxy returns a new host (server supervisor) which
// proxies all requests to the target.
// It uses the httputil.NewSingleHostReverseProxy.
//
// Usage:
// target, _ := url.Parse("https://mydomain.com")
// proxy := NewProxy("mydomain.com:80", target)
// proxy.ListenAndServe() // use of `proxy.Shutdown` to close the proxy server.
func NewProxy(hostAddr string, target *url.URL) *Supervisor {
proxyHandler := ProxyHandler(target)
proxy := New(&http.Server{
Addr: hostAddr,
Handler: proxyHandler,
})
return proxy
}
// NewRedirection returns a new host (server supervisor) which
// redirects all requests to the target.
// Usage:
// target, _ := url.Parse("https://mydomain.com")
// r := NewRedirection(":80", target, 307)
// r.ListenAndServe() // use of `r.Shutdown` to close this server.
func NewRedirection(hostAddr string, target *url.URL, redirectStatus int) *Supervisor {
targetURI := target.String()
if redirectStatus <= 300 {
// here we should use StatusPermanentRedirect but
// that may result on unexpected behavior
// for end-developers who might change their minds
// after a while, so keep status temporary.
// Note thatwe could also use StatusFound
// as we do on the `Context#Redirect`.
// It will also help us to prevent any post data issues.
redirectStatus = http.StatusTemporaryRedirect
}
redirectSrv := &http.Server{
ReadTimeout: 30 * time.Second,
WriteTimeout: 60 * time.Second,
Addr: hostAddr,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
redirectTo := singleJoiningSlash(targetURI, r.URL.Path)
if len(r.URL.RawQuery) > 0 {
redirectTo += "?" + r.URL.RawQuery
}
http.Redirect(w, r, redirectTo, redirectStatus)
}),
}
return New(redirectSrv)
}

@kataras kataras closed this Aug 14, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.