diff options
Diffstat (limited to 'workhorse/internal/sendurl/sendurl_test.go')
-rw-r--r-- | workhorse/internal/sendurl/sendurl_test.go | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/workhorse/internal/sendurl/sendurl_test.go b/workhorse/internal/sendurl/sendurl_test.go new file mode 100644 index 00000000000..41e1dbb8e0f --- /dev/null +++ b/workhorse/internal/sendurl/sendurl_test.go @@ -0,0 +1,197 @@ +package sendurl + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper" +) + +const testData = `123456789012345678901234567890` +const testDataEtag = `W/"myetag"` + +func testEntryServer(t *testing.T, requestURL string, httpHeaders http.Header, allowRedirects bool) *httptest.ResponseRecorder { + requestHandler := func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "GET", r.Method) + + url := r.URL.String() + "/file" + jsonParams := fmt.Sprintf(`{"URL":%q,"AllowRedirects":%s}`, + url, strconv.FormatBool(allowRedirects)) + data := base64.URLEncoding.EncodeToString([]byte(jsonParams)) + + // The server returns a Content-Disposition + w.Header().Set("Content-Disposition", "attachment; filename=\"archive.txt\"") + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Expires", "") + w.Header().Set("Date", "Wed, 21 Oct 2015 05:28:00 GMT") + w.Header().Set("Pragma", "no-cache") + + SendURL.Inject(w, r, data) + } + serveFile := func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "GET", r.Method) + + tempFile, err := ioutil.TempFile("", "download_file") + require.NoError(t, err) + require.NoError(t, os.Remove(tempFile.Name())) + defer tempFile.Close() + _, err = tempFile.Write([]byte(testData)) + require.NoError(t, err) + + w.Header().Set("Etag", testDataEtag) + w.Header().Set("Cache-Control", "public") + w.Header().Set("Expires", "Wed, 21 Oct 2015 07:28:00 GMT") + w.Header().Set("Date", "Wed, 21 Oct 2015 06:28:00 GMT") + w.Header().Set("Pragma", "") + + http.ServeContent(w, r, "archive.txt", time.Now(), tempFile) + } + redirectFile := func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "GET", r.Method) + http.Redirect(w, r, r.URL.String()+"/download", http.StatusTemporaryRedirect) + } + + mux := http.NewServeMux() + mux.HandleFunc("/get/request", requestHandler) + mux.HandleFunc("/get/request/file", serveFile) + mux.HandleFunc("/get/redirect", requestHandler) + mux.HandleFunc("/get/redirect/file", redirectFile) + mux.HandleFunc("/get/redirect/file/download", serveFile) + mux.HandleFunc("/get/file-not-existing", requestHandler) + + server := httptest.NewServer(mux) + defer server.Close() + + httpRequest, err := http.NewRequest("GET", server.URL+requestURL, nil) + require.NoError(t, err) + if httpHeaders != nil { + httpRequest.Header = httpHeaders + } + + response := httptest.NewRecorder() + mux.ServeHTTP(response, httpRequest) + return response +} + +func TestDownloadingUsingSendURL(t *testing.T) { + response := testEntryServer(t, "/get/request", nil, false) + require.Equal(t, http.StatusOK, response.Code) + + testhelper.RequireResponseHeader(t, response, + "Content-Type", + "text/plain; charset=utf-8") + testhelper.RequireResponseHeader(t, response, + "Content-Disposition", + "attachment; filename=\"archive.txt\"") + + testhelper.RequireResponseBody(t, response, testData) +} + +func TestDownloadingAChunkOfDataWithSendURL(t *testing.T) { + httpHeaders := http.Header{ + "Range": []string{ + "bytes=1-2", + }, + } + + response := testEntryServer(t, "/get/request", httpHeaders, false) + require.Equal(t, http.StatusPartialContent, response.Code) + + testhelper.RequireResponseHeader(t, response, + "Content-Type", + "text/plain; charset=utf-8") + testhelper.RequireResponseHeader(t, response, + "Content-Disposition", + "attachment; filename=\"archive.txt\"") + testhelper.RequireResponseHeader(t, response, + "Content-Range", + "bytes 1-2/30") + + testhelper.RequireResponseBody(t, response, "23") +} + +func TestAccessingAlreadyDownloadedFileWithSendURL(t *testing.T) { + httpHeaders := http.Header{ + "If-None-Match": []string{testDataEtag}, + } + + response := testEntryServer(t, "/get/request", httpHeaders, false) + require.Equal(t, http.StatusNotModified, response.Code) +} + +func TestAccessingRedirectWithSendURL(t *testing.T) { + response := testEntryServer(t, "/get/redirect", nil, false) + require.Equal(t, http.StatusTemporaryRedirect, response.Code) +} + +func TestAccessingAllowedRedirectWithSendURL(t *testing.T) { + response := testEntryServer(t, "/get/redirect", nil, true) + require.Equal(t, http.StatusOK, response.Code) + + testhelper.RequireResponseHeader(t, response, + "Content-Type", + "text/plain; charset=utf-8") + testhelper.RequireResponseHeader(t, response, + "Content-Disposition", + "attachment; filename=\"archive.txt\"") +} + +func TestAccessingAllowedRedirectWithChunkOfDataWithSendURL(t *testing.T) { + httpHeaders := http.Header{ + "Range": []string{ + "bytes=1-2", + }, + } + + response := testEntryServer(t, "/get/redirect", httpHeaders, true) + require.Equal(t, http.StatusPartialContent, response.Code) + + testhelper.RequireResponseHeader(t, response, + "Content-Type", + "text/plain; charset=utf-8") + testhelper.RequireResponseHeader(t, response, + "Content-Disposition", + "attachment; filename=\"archive.txt\"") + testhelper.RequireResponseHeader(t, response, + "Content-Range", + "bytes 1-2/30") + + testhelper.RequireResponseBody(t, response, "23") +} + +func TestOriginalCacheHeadersPreservedWithSendURL(t *testing.T) { + response := testEntryServer(t, "/get/redirect", nil, true) + require.Equal(t, http.StatusOK, response.Code) + + testhelper.RequireResponseHeader(t, response, + "Cache-Control", + "no-cache") + testhelper.RequireResponseHeader(t, response, + "Expires", + "") + testhelper.RequireResponseHeader(t, response, + "Date", + "Wed, 21 Oct 2015 05:28:00 GMT") + testhelper.RequireResponseHeader(t, response, + "Pragma", + "no-cache") +} + +func TestDownloadingNonExistingFileUsingSendURL(t *testing.T) { + response := testEntryServer(t, "/invalid/path", nil, false) + require.Equal(t, http.StatusNotFound, response.Code) +} + +func TestDownloadingNonExistingRemoteFileWithSendURL(t *testing.T) { + response := testEntryServer(t, "/get/file-not-existing", nil, false) + require.Equal(t, http.StatusNotFound, response.Code) +} |