[Golang] Direct request from http to https with reverse proxy

Let’s say we have a reverse proxy. The incoming request is HTTP, the target server hosts HTTPs APIs with self-signed TLS certificates.

It is very common that we change the URL host or path with reverse proxy, so that the request can be directed a different API. However, in this case, we also need to add the self-signed certificates in reverse proxy.

The below example will show how to achieve it.

package proxy

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

func NewProxy(addr, caCertPath, certPath, keyPath string) http.Handler {
	remoteURL, _ := url.Parse(addr)

	proxy := httputil.NewSingleHostReverseProxy(remoteURL)

	if certPath != "" && keyPath != "" {
		var caCertPool *x509.CertPool
		// Create a CA certificate pool and add cert.pem to it
		if caCertPath != "" {
			caCert, err := ioutil.ReadFile(caCertPath)
			if err != nil {
				log.Fatalf("[ERROR] [proxy,nomad] [message: failed to read Nomad CA Cert]")
			}
			caCertPool = x509.NewCertPool()
			caCertPool.AppendCertsFromPEM(caCert)
		}

		// Create an HTTPS client and supply the created CA pool and certificate
		proxy.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:    caCertPool,
				MinVersion: tls.VersionTLS13,
				MaxVersion: tls.VersionTLS13,
				GetClientCertificate: func(chi *tls.CertificateRequestInfo) (*tls.Certificate, error) {
					cert, err := tls.LoadX509KeyPair(certPath, keyPath)
					if err != nil {
						return nil, err
					}

					return &cert, nil
				},
			},
		}
	}
	
	return proxy
}

If this post helped you to solve a problem or provided you with new insights, please upvote it and share your experience in the comments below. Your comments can help others who may be facing similar challenges. Thank you!
Buy Me A Coffee
DigitalOcean Referral Badge
Sign up to get $200, 60-day account credit !