diff --git a/api/handler.go b/api/handler.go index cf30d52..4c36f9c 100644 --- a/api/handler.go +++ b/api/handler.go @@ -319,6 +319,15 @@ func healthCheck(w http.ResponseWriter, r *http.Request) { w.Write([]byte("WORKING")) } +func getMimeType(path string, content []byte) string { + extension := filepath.Ext(path) + mimeType := mime.TypeByExtension(extension) + if mimeType == "" { + mimeType = http.DetectContentType(content) + } + return mimeType +} + func getFileContents(w http.ResponseWriter, r *http.Request) { repo := r.URL.Query().Get(":name") path := r.URL.Query().Get("path") @@ -336,12 +345,7 @@ func getFileContents(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusNotFound) return } - extension := filepath.Ext(path) - mimeType := mime.TypeByExtension(extension) - if mimeType == "" { - mimeType = "text/plain; charset=utf-8" - } - w.Header().Set("Content-Type", mimeType) + w.Header().Set("Content-Type", getMimeType(path, contents)) w.Header().Set("Content-Length", strconv.Itoa(len(contents))) w.Write(contents) } diff --git a/api/handler_test.go b/api/handler_test.go index 6ef3c8f..c6f68f9 100644 --- a/api/handler_test.go +++ b/api/handler_test.go @@ -987,6 +987,26 @@ func (s *S) TestGetFileContentsWithoutExtension(c *gocheck.C) { c.Assert(recorder.Header()["Content-Length"][0], gocheck.Equals, "6") } +func (s *S) TestGetBinaryFileContentsWithoutExtension(c *gocheck.C) { + url := "/repository/repo/contents?path=my-binary-file" + expected := new(bytes.Buffer) + expected.Write([]byte{10, 20, 30, 0, 9, 200}) + repository.Retriever = &repository.MockContentRetriever{ + ResultContents: expected.Bytes(), + } + defer func() { + repository.Retriever = nil + }() + request, err := http.NewRequest("GET", url, nil) + c.Assert(err, gocheck.IsNil) + recorder := httptest.NewRecorder() + s.router.ServeHTTP(recorder, request) + c.Assert(recorder.Code, gocheck.Equals, http.StatusOK) + c.Assert(recorder.Body, gocheck.DeepEquals, expected) + c.Assert(recorder.Header()["Content-Type"][0], gocheck.Equals, "application/octet-stream") + c.Assert(recorder.Header()["Content-Length"][0], gocheck.Equals, "6") +} + func (s *S) TestGetFileContentsWithRef(c *gocheck.C) { url := "/repository/repo/contents?path=README.txt&ref=other" expected := "result" @@ -1592,3 +1612,25 @@ func (s *S) TestLogsWithPath(c *gocheck.C) { c.Assert(obj.Commits, gocheck.HasLen, 1) c.Assert(obj.Commits[0], gocheck.DeepEquals, commits[0]) } + +func (s *S) TestGetMimeTypeFromExtension(c *gocheck.C) { + path := "my-text-file.txt" + content := new(bytes.Buffer) + content.WriteString("") + c.Assert(getMimeType(path, content.Bytes()), gocheck.Equals, "text/plain; charset=utf-8") + path = "my-text-file.sh" + content = new(bytes.Buffer) + content.WriteString("") + c.Assert(getMimeType(path, content.Bytes()), gocheck.Equals, "application/x-sh") +} + +func (s *S) TestGetMimeTypeFromContent(c *gocheck.C) { + path := "README" + content := new(bytes.Buffer) + content.WriteString("thou shalt not pass") + c.Assert(getMimeType(path, content.Bytes()), gocheck.Equals, "text/plain; charset=utf-8") + path = "my-binary-file" + content = new(bytes.Buffer) + content.Write([]byte{10, 20, 30, 0, 9, 200}) + c.Assert(getMimeType(path, content.Bytes()), gocheck.Equals, "application/octet-stream") +}