feat: publish sanitized custom.97 source

This commit is contained in:
cneicy committed 2026-10-27 20:43:39 +08:00
1 parent 8e6ed0317b
commit 86c0276156
1022 files changed
+69903 -19207

No files matched your search

+103 -6
View File
@@ -4,13 +4,16 @@ import (
"context"
"fmt"
"net/http"
"strconv"
"sync/atomic"
"testing"
"time"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/i18n"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/setting"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -43,17 +46,18 @@ func TestModelRedisRateLimitUsesUTCRegardlessOfLocalTimezone(t *testing.T) {
var modelRateLimitTestUsers atomic.Int64
func TestModelRateLimitStreamFailuresDoNotConsumeSuccessLimit(t *testing.T) {
require.NoError(t, i18n.Init())
for _, backend := range []string{"memory", "redis"} {
for _, totalLimit := range []int{0, 2} {
t.Run(fmt.Sprintf("%s/total=%d", backend, totalLimit), func(t *testing.T) {
userID := 7200000 + int(modelRateLimitTestUsers.Add(1))
handler := memoryRateLimitHandler(60, totalLimit, 1)
subject := strconv.Itoa(7200000 + int(modelRateLimitTestUsers.Add(1)))
handler := memoryRateLimitHandler(subject, 60, totalLimit, 1)
if backend == "redis" {
useRateLimitMiniRedis(t)
handler = redisRateLimitHandler(60, totalLimit, 1)
handler = redisRateLimitHandler(subject, 60, totalLimit, 1)
}
router := gin.New()
router.GET("/:outcome", func(c *gin.Context) { c.Set("id", userID) }, handler, func(c *gin.Context) {
router.GET("/:outcome", handler, func(c *gin.Context) {
status := relaycommon.NewStreamStatus()
if c.Param("outcome") == "failed" {
status.MarkFailed("server_error", "", 0)
@@ -76,10 +80,11 @@ func TestModelRateLimitStreamFailuresDoNotConsumeSuccessLimit(t *testing.T) {
}
func TestModelMemoryRateLimitReservesConcurrentSuccessAdmission(t *testing.T) {
userID := 7200000 + int(modelRateLimitTestUsers.Add(1))
require.NoError(t, i18n.Init())
subject := strconv.Itoa(7200000 + int(modelRateLimitTestUsers.Add(1)))
entered, release, finished := make(chan struct{}), make(chan struct{}), make(chan struct{})
router := gin.New()
router.GET("/:outcome", func(c *gin.Context) { c.Set("id", userID) }, memoryRateLimitHandler(60, 0, 1), func(c *gin.Context) {
router.GET("/:outcome", memoryRateLimitHandler(subject, 60, 0, 1), func(c *gin.Context) {
if c.Param("outcome") == "failed" {
close(entered)
<-release
@@ -100,3 +105,95 @@ func TestModelMemoryRateLimitReservesConcurrentSuccessAdmission(t *testing.T) {
assert.Equal(t, http.StatusOK, performRateLimitRequest(router, "/completed", "127.0.0.1:1000").Code)
assert.Equal(t, http.StatusTooManyRequests, performRateLimitRequest(router, "/completed", "127.0.0.1:1000").Code)
}
// The memory limiter answers like the Redis limiter: an OpenAI error body
// naming the limit that was reached, not an empty 429.
func TestModelMemoryRateLimitRejectionsReturnOpenAIError(t *testing.T) {
require.NoError(t, i18n.Init())
for _, tc := range []struct {
name string
totalLimit, successLimit int
messageKey string
}{
{name: "total", totalLimit: 1, messageKey: i18n.MsgRateLimitTotalReached},
{name: "success", successLimit: 1, messageKey: i18n.MsgRateLimitReached},
} {
t.Run(tc.name, func(t *testing.T) {
subject := strconv.Itoa(7200000 + int(modelRateLimitTestUsers.Add(1)))
router := gin.New()
router.GET("/", func(c *gin.Context) {
c.Set(common.RequestIdKey, "req-limited")
}, memoryRateLimitHandler(subject, 60, tc.totalLimit, tc.successLimit), func(c *gin.Context) {
c.Status(http.StatusOK)
})
require.Equal(t, http.StatusOK, performRateLimitRequest(router, "/", "127.0.0.1:1000").Code)
resp := performRateLimitRequest(router, "/", "127.0.0.1:1000")
assert.Equal(t, http.StatusTooManyRequests, resp.Code)
message := i18n.Translate("", tc.messageKey, map[string]any{"Minutes": setting.ModelRequestRateLimitDurationMinutes, "Max": 1})
want, err := common.Marshal(gin.H{"error": gin.H{
"message": common.MessageWithRequestId(message, "req-limited"),
"type": "new_api_error",
"code": "",
}})
require.NoError(t, err)
assert.JSONEq(t, string(want), resp.Body.String())
})
}
}
// A group with its own limit counts each user's requests on its own; groups
// without one keep sharing the user's global limit.
func TestModelRateLimitCountsConfiguredGroupsSeparately(t *testing.T) {
require.NoError(t, i18n.Init())
previousEnabled, previousMinutes := setting.ModelRequestRateLimitEnabled, setting.ModelRequestRateLimitDurationMinutes
previousTotal, previousSuccess := setting.ModelRequestRateLimitCount, setting.ModelRequestRateLimitSuccessCount
previousGroups, previousRedisEnabled := setting.ModelRequestRateLimitGroup, common.RedisEnabled
t.Cleanup(func() {
setting.ModelRequestRateLimitEnabled, setting.ModelRequestRateLimitDurationMinutes = previousEnabled, previousMinutes
setting.ModelRequestRateLimitCount, setting.ModelRequestRateLimitSuccessCount = previousTotal, previousSuccess
setting.ModelRequestRateLimitGroup, common.RedisEnabled = previousGroups, previousRedisEnabled
})
setting.ModelRequestRateLimitEnabled, setting.ModelRequestRateLimitDurationMinutes = true, 1
common.RedisEnabled = false
// Groups a and b have their own limits; c and d have none and share the global one.
steps := []struct {
group string
want int
}{
{"a", http.StatusOK}, {"a", http.StatusTooManyRequests},
{"b", http.StatusOK}, {"b", http.StatusTooManyRequests},
{"c", http.StatusOK}, {"d", http.StatusTooManyRequests},
}
// The Redis token bucket binds to the first Redis client it sees and another
// test already drives it, so the total limit runs on the memory backend only.
for _, tc := range []struct {
backend, limit string
counts [2]int // [total, success] for groups a and b and for the global limit
}{
{"memory", "success", [2]int{0, 1}},
{"redis", "success", [2]int{0, 1}},
{"memory", "total", [2]int{1, 1000}},
} {
t.Run(tc.backend+"/"+tc.limit, func(t *testing.T) {
if tc.backend == "redis" {
useRateLimitMiniRedis(t)
}
setting.ModelRequestRateLimitCount, setting.ModelRequestRateLimitSuccessCount = tc.counts[0], tc.counts[1]
setting.ModelRequestRateLimitGroup = map[string][2]int{"a": tc.counts, "b": tc.counts}
userID := 7200000 + int(modelRateLimitTestUsers.Add(1))
router := gin.New()
router.GET("/:group", func(c *gin.Context) {
c.Set("id", userID)
common.SetContextKey(c, constant.ContextKeyTokenGroup, c.Param("group"))
}, ModelRequestRateLimit(), func(c *gin.Context) {
c.Status(http.StatusOK)
})
for _, step := range steps {
assert.Equal(t, step.want, performRateLimitRequest(router, "/"+step.group, "127.0.0.1:1000").Code, "group %s", step.group)
}
})
}
}