2023-05-09 09:34:36 +02:00
|
|
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
package httplib
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2023-05-13 16:04:57 +02:00
|
|
|
"net/http/httptest"
|
2023-05-09 09:34:36 +02:00
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2024-07-30 21:41:27 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-05-09 09:34:36 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestServeContentByReader(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", fmt.Sprintf("bytes=%s", rangeStr))
|
|
|
|
}
|
|
|
|
reader := strings.NewReader(data)
|
2023-05-13 16:04:57 +02:00
|
|
|
w := httptest.NewRecorder()
|
2023-05-09 09:34:36 +02:00
|
|
|
ServeContentByReader(r, w, "test", int64(len(data)), reader)
|
2023-05-13 16:04:57 +02:00
|
|
|
assert.Equal(t, expectedStatusCode, w.Code)
|
2023-05-09 09:34:36 +02:00
|
|
|
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
|
|
|
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
|
2023-05-13 16:04:57 +02:00
|
|
|
assert.Equal(t, expectedContent, w.Body.String())
|
2023-05-09 09:34:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 TestServeContentByReadSeeker(t *testing.T) {
|
|
|
|
data := "0123456789abcdef"
|
|
|
|
tmpFile := t.TempDir() + "/test"
|
|
|
|
err := os.WriteFile(tmpFile, []byte(data), 0o644)
|
2024-07-30 21:41:27 +02:00
|
|
|
require.NoError(t, err)
|
2023-05-09 09:34:36 +02:00
|
|
|
|
|
|
|
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", fmt.Sprintf("bytes=%s", rangeStr))
|
|
|
|
}
|
|
|
|
|
|
|
|
seekReader, err := os.OpenFile(tmpFile, os.O_RDONLY, 0o644)
|
2024-07-30 21:41:27 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-05-09 09:34:36 +02:00
|
|
|
defer seekReader.Close()
|
|
|
|
|
2023-05-13 16:04:57 +02:00
|
|
|
w := httptest.NewRecorder()
|
2023-07-07 07:31:56 +02:00
|
|
|
ServeContentByReadSeeker(r, w, "test", nil, seekReader)
|
2023-05-13 16:04:57 +02:00
|
|
|
assert.Equal(t, expectedStatusCode, w.Code)
|
2023-05-09 09:34:36 +02:00
|
|
|
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
|
|
|
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
|
2023-05-13 16:04:57 +02:00
|
|
|
assert.Equal(t, expectedContent, w.Body.String())
|
2023-05-09 09:34:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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:])
|
|
|
|
})
|
|
|
|
}
|