Commit 315356ed authored by Jacob Vosmaer's avatar Jacob Vosmaer

Move upload handling into internal/upload

parent 39b50833
...@@ -5,23 +5,35 @@ import ( ...@@ -5,23 +5,35 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"sync"
) )
type Proxy struct { type Proxy struct {
reverseProxy *httputil.ReverseProxy URL string
version string Version string
Transport http.RoundTripper
_reverseProxy *httputil.ReverseProxy
configureReverseProxyOnce sync.Once
} }
func NewProxy(url *url.URL, transport http.RoundTripper, version string) *Proxy { func (p *Proxy) reverseProxy() *httputil.ReverseProxy {
p.configureReverseProxyOnce.Do(p.configureReverseProxy)
return p._reverseProxy
}
func (p *Proxy) configureReverseProxy() {
// Modify a copy of url // Modify a copy of url
proxyURL := *url url, err := url.Parse(p.URL)
proxyURL.Path = "" if err != nil {
p := Proxy{reverseProxy: httputil.NewSingleHostReverseProxy(&proxyURL), version: version} log.Fatalf("configureReverseProxy: %v", err)
p.reverseProxy.Transport = transport }
return &p url.Path = ""
p._reverseProxy = httputil.NewSingleHostReverseProxy(url)
p._reverseProxy.Transport = p.Transport
} }
type RoundTripper struct { type RoundTripper struct {
...@@ -78,9 +90,9 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -78,9 +90,9 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
req.Header = HeaderClone(r.Header) req.Header = HeaderClone(r.Header)
// Set Workhorse version // Set Workhorse version
req.Header.Set("Gitlab-Workhorse", p.version) req.Header.Set("Gitlab-Workhorse", p.Version)
rw := newSendFileResponseWriter(w, &req) rw := newSendFileResponseWriter(w, &req)
defer rw.Flush() defer rw.Flush()
p.reverseProxy.ServeHTTP(&rw, &req) p.reverseProxy().ServeHTTP(&rw, &req)
} }
package upstream package upload
import ( import (
"../api" "../api"
"net/http" "net/http"
) )
func artifactsAuthorizeHandler(myAPI *api.API, h http.HandlerFunc) http.HandlerFunc { func Artifacts(myAPI *api.API, h http.Handler) http.Handler {
return myAPI.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) { return myAPI.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {
r.Header.Set(tempPathHeader, a.TempPath) r.Header.Set(tempPathHeader, a.TempPath)
h(w, r) h.ServeHTTP(w, r)
}, "/authorize") }, "/authorize")
} }
package upstream package upload
import ( import (
"../helper" "../helper"
......
package upstream package upload
import ( import (
"../helper" "../helper"
"../proxy"
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
...@@ -13,7 +14,6 @@ import ( ...@@ -13,7 +14,6 @@ import (
"regexp" "regexp"
"strings" "strings"
"testing" "testing"
"time"
) )
var nilHandler = http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}) var nilHandler = http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})
...@@ -40,6 +40,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) { ...@@ -40,6 +40,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
w.WriteHeader(202) w.WriteHeader(202)
fmt.Fprint(w, "RESPONSE") fmt.Fprint(w, "RESPONSE")
}) })
defer ts.Close()
httpRequest, err := http.NewRequest("PATCH", ts.URL+"/url/path", bytes.NewBufferString("REQUEST")) httpRequest, err := http.NewRequest("PATCH", ts.URL+"/url/path", bytes.NewBufferString("REQUEST"))
if err != nil { if err != nil {
...@@ -56,7 +57,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) { ...@@ -56,7 +57,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
httpRequest.Header.Set(tempPathHeader, tempPath) httpRequest.Header.Set(tempPathHeader, tempPath)
handleFileUploads(New(ts.URL, "", "123", time.Second).Proxy).ServeHTTP(response, httpRequest) handleFileUploads(&proxy.Proxy{URL: ts.URL, Version: "123"}).ServeHTTP(response, httpRequest)
helper.AssertResponseCode(t, response, 202) helper.AssertResponseCode(t, response, 202)
if response.Body.String() != "RESPONSE" { if response.Body.String() != "RESPONSE" {
t.Fatal("Expected RESPONSE in response body") t.Fatal("Expected RESPONSE in response body")
...@@ -129,9 +130,8 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) { ...@@ -129,9 +130,8 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
httpRequest.Header.Set("Content-Type", writer.FormDataContentType()) httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
httpRequest.Header.Set(tempPathHeader, tempPath) httpRequest.Header.Set(tempPathHeader, tempPath)
response := httptest.NewRecorder() response := httptest.NewRecorder()
u := New(ts.URL, "", "123", time.Second)
handleFileUploads(u.Proxy).ServeHTTP(response, httpRequest) handleFileUploads(&proxy.Proxy{URL: ts.URL, Version: "123"}).ServeHTTP(response, httpRequest)
helper.AssertResponseCode(t, response, 202) helper.AssertResponseCode(t, response, 202)
if _, err := os.Stat(filePath); !os.IsNotExist(err) { if _, err := os.Stat(filePath); !os.IsNotExist(err) {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"../errorpage" "../errorpage"
"../git" "../git"
"../lfs" "../lfs"
"../upload"
"net/http" "net/http"
"regexp" "regexp"
) )
...@@ -50,7 +51,7 @@ func (u *Upstream) compileRoutes() { ...@@ -50,7 +51,7 @@ func (u *Upstream) compileRoutes() {
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.bz2\z`), git.GetArchive(u.API)}, route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.bz2\z`), git.GetArchive(u.API)},
// CI Artifacts API // CI Artifacts API
route{"POST", regexp.MustCompile(ciAPIPattern + `v1/builds/[0-9]+/artifacts\z`), contentEncodingHandler(artifactsAuthorizeHandler(u.API, handleFileUploads(u.Proxy)))}, route{"POST", regexp.MustCompile(ciAPIPattern + `v1/builds/[0-9]+/artifacts\z`), contentEncodingHandler(upload.Artifacts(u.API, u.Proxy))},
// Explicitly u.Proxy API requests // Explicitly u.Proxy API requests
route{"", regexp.MustCompile(apiPattern), u.Proxy}, route{"", regexp.MustCompile(apiPattern), u.Proxy},
......
...@@ -64,7 +64,7 @@ func New(authBackend string, authSocket string, version string, responseHeadersT ...@@ -64,7 +64,7 @@ func New(authBackend string, authSocket string, version string, responseHeadersT
URL: parsedURL, URL: parsedURL,
Version: version, Version: version,
}, },
Proxy: proxy.NewProxy(parsedURL, proxyTransport, version), Proxy: &proxy.Proxy{URL: authBackend, Transport: proxyTransport, Version: version},
urlPrefix: urlPrefix(relativeURLRoot), urlPrefix: urlPrefix(relativeURLRoot),
} }
up.compileRoutes() up.compileRoutes()
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
"net" "net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url"
"regexp" "regexp"
"testing" "testing"
"time" "time"
...@@ -94,15 +93,10 @@ func TestProxyReadTimeout(t *testing.T) { ...@@ -94,15 +93,10 @@ func TestProxyReadTimeout(t *testing.T) {
}, },
) )
u := newUpstream(ts.URL) p := &proxy.Proxy{URL: ts.URL, Transport: transport, Version: "123"}
url, err := url.Parse(ts.URL)
if err != nil {
t.Fatal(err)
}
u.Proxy = proxy.NewProxy(url, transport, "123")
w := httptest.NewRecorder() w := httptest.NewRecorder()
u.Proxy.ServeHTTP(w, httpRequest) p.ServeHTTP(w, httpRequest)
helper.AssertResponseCode(t, w, 502) helper.AssertResponseCode(t, w, 502)
helper.AssertResponseBody(t, w, "net/http: timeout awaiting response headers") helper.AssertResponseBody(t, w, "net/http: timeout awaiting response headers")
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment