summaryrefslogtreecommitdiff
path: root/workhorse/internal/proxy/proxy.go
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/proxy/proxy.go')
-rw-r--r--workhorse/internal/proxy/proxy.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/workhorse/internal/proxy/proxy.go b/workhorse/internal/proxy/proxy.go
new file mode 100644
index 00000000000..1bc417a841f
--- /dev/null
+++ b/workhorse/internal/proxy/proxy.go
@@ -0,0 +1,62 @@
+package proxy
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+ "time"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+)
+
+var (
+ defaultTarget = helper.URLMustParse("http://localhost")
+)
+
+type Proxy struct {
+ Version string
+ reverseProxy *httputil.ReverseProxy
+ AllowResponseBuffering bool
+}
+
+func NewProxy(myURL *url.URL, version string, roundTripper http.RoundTripper) *Proxy {
+ p := Proxy{Version: version, AllowResponseBuffering: true}
+
+ if myURL == nil {
+ myURL = defaultTarget
+ }
+
+ u := *myURL // Make a copy of p.URL
+ u.Path = ""
+ p.reverseProxy = httputil.NewSingleHostReverseProxy(&u)
+ p.reverseProxy.Transport = roundTripper
+ return &p
+}
+
+func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Clone request
+ req := *r
+ req.Header = helper.HeaderClone(r.Header)
+
+ // Set Workhorse version
+ req.Header.Set("Gitlab-Workhorse", p.Version)
+ req.Header.Set("Gitlab-Workhorse-Proxy-Start", fmt.Sprintf("%d", time.Now().UnixNano()))
+
+ if p.AllowResponseBuffering {
+ helper.AllowResponseBuffering(w)
+ }
+
+ // If the ultimate client disconnects when the response isn't fully written
+ // to them yet, httputil.ReverseProxy panics with a net/http.ErrAbortHandler
+ // error. We can catch and discard this to keep the error log clean
+ defer func() {
+ if err := recover(); err != nil {
+ if err != http.ErrAbortHandler {
+ panic(err)
+ }
+ }
+ }()
+
+ p.reverseProxy.ServeHTTP(w, &req)
+}