relay/channel/api_request_redirect_test.go
Rama main · réplica de lectura del repositorio original.
package channel
import (
"bytes"
"io"
"net/http"
"net/http/httptest"
"reflect"
"sync/atomic"
"testing"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/service"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDoRequestReturnsUpstreamRedirectWithoutFollowing(t *testing.T) {
service.InitHttpClient()
gin.SetMode(gin.TestMode)
sharedClient := service.GetHttpClient()
require.NotNil(t, sharedClient)
require.NotNil(t, sharedClient.CheckRedirect)
originalRedirectPolicy := reflect.ValueOf(sharedClient.CheckRedirect).Pointer()
var targetRequests atomic.Int32
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
targetRequests.Add(1)
w.WriteHeader(http.StatusTeapot)
}))
defer target.Close()
const responseBody = "redirect response"
tests := []int{
http.StatusMovedPermanently,
http.StatusFound,
http.StatusSeeOther,
http.StatusTemporaryRedirect,
http.StatusPermanentRedirect,
}
for _, statusCode := range tests {
t.Run(http.StatusText(statusCode), func(t *testing.T) {
targetRequests.Store(0)
var sourceRequests atomic.Int32
type sourceResult struct {
body []byte
err error
}
sourceResultCh := make(chan sourceResult, 1)
source := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sourceRequests.Add(1)
body, err := io.ReadAll(r.Body)
sourceResultCh <- sourceResult{body: body, err: err}
w.Header().Set("Location", target.URL+"/redirect-target")
w.WriteHeader(statusCode)
_, _ = io.WriteString(w, responseBody)
}))
defer source.Close()
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.Request = httptest.NewRequest(http.MethodPost, "/relay", nil)
req, err := http.NewRequest(http.MethodPost, source.URL, bytes.NewReader([]byte("request body")))
require.NoError(t, err)
info := &relaycommon.RelayInfo{ChannelMeta: &relaycommon.ChannelMeta{}}
resp, err := doRequest(ctx, req, info)
require.NoError(t, err)
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
gotSource := <-sourceResultCh
require.NoError(t, gotSource.err)
assert.Equal(t, statusCode, resp.StatusCode)
assert.Equal(t, target.URL+"/redirect-target", resp.Header.Get("Location"))
assert.Equal(t, responseBody, string(body))
assert.Equal(t, []byte("request body"), gotSource.body)
assert.EqualValues(t, 1, sourceRequests.Load())
assert.Zero(t, targetRequests.Load())
})
}
assert.Equal(t, originalRedirectPolicy, reflect.ValueOf(sharedClient.CheckRedirect).Pointer(), "the cached client must not be mutated")
}