1
1
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-07 13:16:38 +02:00
Files
gitea/modules/httplib/serve_test.go
2026-05-05 18:21:07 +00:00

144 lines
4.5 KiB
Go

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package httplib
import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"strconv"
"strings"
"testing"
"code.gitea.io/gitea/modules/typesniffer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestServeUserContentByReader(t *testing.T) {
data := "0123456789abcdef"
test := func(t *testing.T, expectedStatusCode int, expectedContent string) {
_, rangeStr, _ := strings.Cut(t.Name(), "_range_")
r := &http.Request{Header: http.Header{}, Form: url.Values{}}
if rangeStr != "" {
r.Header.Set("Range", "bytes="+rangeStr)
}
reader := strings.NewReader(data)
w := httptest.NewRecorder()
ServeUserContentByReader(r, w, int64(len(data)), reader, ServeHeaderOptions{})
assert.Equal(t, expectedStatusCode, w.Code)
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
assert.Equal(t, strconv.Itoa(len(expectedContent)), w.Header().Get("Content-Length"))
assert.Equal(t, expectedContent, w.Body.String())
}
}
t.Run("_range_", func(t *testing.T) {
test(t, http.StatusOK, data)
})
t.Run("_range_0-", func(t *testing.T) {
test(t, http.StatusPartialContent, data)
})
t.Run("_range_0-15", func(t *testing.T) {
test(t, http.StatusPartialContent, data)
})
t.Run("_range_1-", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:])
})
t.Run("_range_1-3", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:3+1])
})
t.Run("_range_16-", func(t *testing.T) {
test(t, http.StatusRequestedRangeNotSatisfiable, "")
})
t.Run("_range_1-99999", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:])
})
}
func TestServeUserContentByFile(t *testing.T) {
data := "0123456789abcdef"
tmpFile := t.TempDir() + "/test"
err := os.WriteFile(tmpFile, []byte(data), 0o644)
assert.NoError(t, err)
test := func(t *testing.T, expectedStatusCode int, expectedContent string) {
_, rangeStr, _ := strings.Cut(t.Name(), "_range_")
r := &http.Request{Header: http.Header{}, Form: url.Values{}}
if rangeStr != "" {
r.Header.Set("Range", "bytes="+rangeStr)
}
seekReader, err := os.OpenFile(tmpFile, os.O_RDONLY, 0o644)
require.NoError(t, err)
defer seekReader.Close()
w := httptest.NewRecorder()
ServeUserContentByFile(r, w, seekReader, ServeHeaderOptions{})
assert.Equal(t, expectedStatusCode, w.Code)
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
assert.Equal(t, strconv.Itoa(len(expectedContent)), w.Header().Get("Content-Length"))
assert.Equal(t, expectedContent, w.Body.String())
}
}
t.Run("_range_", func(t *testing.T) {
test(t, http.StatusOK, data)
})
t.Run("_range_0-", func(t *testing.T) {
test(t, http.StatusPartialContent, data)
})
t.Run("_range_0-15", func(t *testing.T) {
test(t, http.StatusPartialContent, data)
})
t.Run("_range_1-", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:])
})
t.Run("_range_1-3", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:3+1])
})
t.Run("_range_16-", func(t *testing.T) {
test(t, http.StatusRequestedRangeNotSatisfiable, "")
})
t.Run("_range_1-99999", func(t *testing.T) {
test(t, http.StatusPartialContent, data[1:])
})
}
func TestServeSetHeaderContentRelated(t *testing.T) {
cases := []struct {
contentType string
csp string
}{
{"", serveHeaderCspDefault},
{"any", serveHeaderCspDefault},
{"application/pdf", serveHeaderCspPdf},
{"application/pdf; other", serveHeaderCspPdf},
{"audio/mp4", serveHeaderCspAudioVideo},
{"video/ogg; other", serveHeaderCspAudioVideo},
{typesniffer.MimeTypeImageSvg, serveHeaderCspDefault},
}
for _, c := range cases {
w := httptest.NewRecorder()
serveSetHeaderContentRelated(w, c.contentType)
csp := w.Header().Get("Content-Security-Policy")
assert.Equal(t, c.csp, csp, "content-type: %s", c.contentType)
assert.Equal(t, "nosniff", w.Header().Get("X-Content-Type-Options")) // it should always be there
}
// make sure sandboxed
require.Contains(t, serveHeaderCspDefault, "; sandbox")
}
func TestServeSetHeaders(t *testing.T) {
w := httptest.NewRecorder()
ServeSetHeaders(w, ServeHeaderOptions{Filename: "foo.zip"})
assert.Equal(t, "attachment; filename=foo.zip", w.Header().Get("Content-Disposition"))
ServeSetHeaders(w, ServeHeaderOptions{Filename: "foo.zip", ContentDisposition: ContentDispositionInline})
assert.Equal(t, "inline; filename=foo.zip", w.Header().Get("Content-Disposition"))
}