Buy Me a Coffee

[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
}

Enjoyed this article? Support my work with a coffee ☕ on Ko-fi.
Buy Me a Coffee at ko-fi.com
DigitalOcean Referral Badge
Sign up to get $200, 60-day account credit !