mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2026-10-22 04:32:02 +02:00
Add support for unix socket as upstream (#1866)
* Add support for unix socket as upstream * Add CHANGELOG.md entry * Add Unix socket documentation * Don't export unixRoundTripper, switch from string prefix to Scheme match * Add basic unix server mock * Add some tests and comments
This commit is contained in:
+34
-1
@@ -1,6 +1,8 @@
|
||||
package upstream
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@@ -18,6 +20,7 @@ const (
|
||||
|
||||
httpScheme = "http"
|
||||
httpsScheme = "https"
|
||||
unixScheme = "unix"
|
||||
)
|
||||
|
||||
// SignatureHeaders contains the headers to be signed by the hmac algorithm
|
||||
@@ -40,7 +43,10 @@ var SignatureHeaders = []string{
|
||||
// to a single upstream host.
|
||||
func newHTTPUpstreamProxy(upstream options.Upstream, u *url.URL, sigData *options.SignatureData, errorHandler ProxyErrorHandler) http.Handler {
|
||||
// Set path to empty so that request paths start at the server root
|
||||
u.Path = ""
|
||||
// Unix scheme need the path to find the socket
|
||||
if u.Scheme != "unix" {
|
||||
u.Path = ""
|
||||
}
|
||||
|
||||
// Create a ReverseProxy
|
||||
proxy := newReverseProxy(u, upstream, errorHandler)
|
||||
@@ -92,6 +98,25 @@ func (h *httpUpstreamProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// Unix implementation of http.RoundTripper, required to register unix protocol in reverse proxy
|
||||
type unixRoundTripper struct {
|
||||
Transport *http.Transport
|
||||
}
|
||||
|
||||
// Implementation of https://pkg.go.dev/net/http#RoundTripper interface to support http protocol over unix socket
|
||||
func (t *unixRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
// Inspired by https://github.com/tv42/httpunix
|
||||
// Not having a Host, even if not used, makes the reverseproxy fail with a "no Host in request URL"
|
||||
if req.Host == "" {
|
||||
req.Host = "localhost"
|
||||
}
|
||||
req.URL.Host = req.Host
|
||||
tt := t.Transport
|
||||
req = req.Clone(req.Context())
|
||||
req.URL.Scheme = "http"
|
||||
return tt.RoundTrip(req)
|
||||
}
|
||||
|
||||
// newReverseProxy creates a new reverse proxy for proxying requests to upstream
|
||||
// servers based on the upstream configuration provided.
|
||||
// The proxy should render an error page if there are failures connecting to the
|
||||
@@ -102,6 +127,14 @@ func newReverseProxy(target *url.URL, upstream options.Upstream, errorHandler Pr
|
||||
// Inherit default transport options from Go's stdlib
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
|
||||
if target.Scheme == "unix" {
|
||||
transport.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
dialer := net.Dialer{}
|
||||
return dialer.DialContext(ctx, target.Scheme, target.Path)
|
||||
}
|
||||
transport.RegisterProtocol(target.Scheme, &unixRoundTripper{Transport: transport})
|
||||
}
|
||||
|
||||
// Change default duration for waiting for an upstream response
|
||||
if upstream.Timeout != nil {
|
||||
transport.ResponseHeaderTimeout = upstream.Timeout.Duration()
|
||||
|
||||
Reference in New Issue
Block a user