mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-07 13:16:38 +02:00
58a66cae3c
Backport #37552 Fix #37550 Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
144 lines
4.5 KiB
Go
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"))
|
|
}
|