gin icon indicating copy to clipboard operation
gin copied to clipboard

Draft: add X-Forwarded-Proto support

Open phith0n opened this issue 2 years ago • 1 comments

This PR is a draft, it's objective is to add a new function that is used to obtain the scheme from remote user's request. I'm not sure if this proposal will be accept by yours, so I haven't added tests and document until we can confirm it.

As you know, many servers are run behind a proxy server, that's why Gin has the mechanism like c.ClientIP() that is used to get client address from HTTP header.

In addition to the IP address, server's HTTPS certification is always configured in the proxy server too, such as Nginx, Caddy, Cloudflare. Caddy and Cloudflare are both use X-Forwarded-Proto to told the web app if the client user visit them by https or not.

Other web framework like Django also have a setting that is able to allow a trusted scheme header.

Currently Gin doesn't have a trusted method to get X-Forwarded-Proto like X-Forwarded-For. Be similar to X-Forwarded-For, we have to check if the remote ip is a trusted proxy server before getting the header. So I create this PR to implement it.

Referring to the ClientIP function, the new ClientProto function will like that:

func (c *Context) ClientProto() string {
	var isTls = c.Request.TLS != nil
	remoteIP := net.ParseIP(c.RemoteIP())
	if remoteIP == nil {
		return ""
	}
	trusted := c.engine.isTrustedProxy(remoteIP)

	if trusted && c.engine.ForwardedByClientProto && c.engine.RemoteProtoHeaders != nil {
		for _, headerName := range c.engine.RemoteProtoHeaders {
			proto, valid := c.engine.validateHeader(c.requestHeader(headerName))
			if valid {
				return proto
			}
		}
	}

	if isTls {
		return "https"
	} else {
		return "http"
	}
}

Looking forward your reply, we can discuss about it.

phith0n avatar Dec 24 '22 20:12 phith0n

Another idea is to add a new function c.FromTrustedProxy() to gin.Context. Developers can use this function to check if the request is from a trusted proxy server, then write their own code to get any HTTP header safely.

See https://github.com/gin-gonic/gin/pull/3448

phith0n avatar Dec 24 '22 20:12 phith0n