echo icon indicating copy to clipboard operation
echo copied to clipboard

middleware proxy pass origin Host header

Open art-frela opened this issue 1 year ago • 2 comments

Issue Description

Requests that reach the final server contain the Host header from the original request. If the destination server checks the header Host (eg: ingress in k8s cluster with Host rules) and if the values ​​do not match, then the request is rejected or etc...

Checklist

  • [x] Dependencies installed
  • [x] No typos
  • [x] Searched existing issues and docs

Expected behaviour

proxy replace request.Host to target.URL.Host

Actual behaviour

request.Host stay immutable

Steps to reproduce

  • http server which checks Host header (srv1)
  • http server with echo using middleware proxy (proxy) - target url to srv1, domain for proxy <> domain for srv1
  • run both srv1 and proxy
  • request to proxy

client (localhost) --(Host: proxy.domain.com)--> proxy (proxy.domain.com) --(Host: proxy.domain.com)--> srv1 (srv1.domain.com)

Version/commit

echo v4.12.0

dirty workaround

req.Host = tgt.URL.Host

P.S. Maybe add option to ProxyConfig

art-frela avatar Jun 13 '24 10:06 art-frela

You can do this right now by adding a custom Transport.

Here is an example where I had to Reverse Proxy for minio presigned urls to work when minio is running in k8s.

type customRoundTripper struct {
	Host   string
}

func (c *customRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	r.Host = c.Host
	return http.DefaultTransport.RoundTrip(r)
}

func setupHttp() {
	url1, err := url.Parse("http://minio-s3:9000")
	if err != nil {
		log.Fatal().Err(err).Msg("failed to parse url")
	}
	targets := []*middleware.ProxyTarget{
		{
			URL: url1,
		},
	}
	// We need to change the host by using a custom http.RoundTripper
	// Use a group to proxy path /minio
	g := echo.Group("/minio")
	g.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
		Balancer: middleware.NewRoundRobinBalancer(targets),
		// Strip out the /minio
		Rewrite:   map[string]string{"/minio/*": "/$1"},
		Transport: &customRoundTripper{s.logger, s.cfg.S3.URL},
	}))
}

steffkelsey avatar Jul 22 '24 11:07 steffkelsey

@steffkelsey Thanks for this! I had a much more complex solution in place, this is exactly what's required 😆

bas-ie avatar Jun 10 '25 01:06 bas-ie