Files
new-api-custom/router/relay-router.go
T
Codex bb7968b612
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
feat: publish v1.0.0-rc.36-custom.1
2026-09-11 05:07:48 +08:00

219 lines
8.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package router
import (
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/controller"
"github.com/QuantumNous/new-api/middleware"
"github.com/QuantumNous/new-api/relay"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/gin-gonic/gin"
)
func SetRelayRouter(router *gin.Engine) {
router.Use(middleware.CORS())
router.Use(middleware.DecompressRequestMiddleware())
router.Use(middleware.BodyStorageCleanup()) // 清理请求体存储
router.Use(middleware.StatsMiddleware())
// https://platform.openai.com/docs/api-reference/introduction
modelsRouter := router.Group("/v1/models")
modelsRouter.Use(middleware.RouteTag("relay"))
modelsRouter.Use(middleware.TokenAuth())
{
modelsRouter.GET("", func(c *gin.Context) {
switch {
case c.GetHeader("x-api-key") != "" && c.GetHeader("anthropic-version") != "":
controller.ListModels(c, constant.ChannelTypeAnthropic)
case c.GetHeader("x-goog-api-key") != "" || c.Query("key") != "": // 单独的适配
controller.ListModels(c, constant.ChannelTypeGemini)
default:
controller.ListModels(c, constant.ChannelTypeOpenAI)
}
})
modelsRouter.GET("/:model", func(c *gin.Context) {
switch {
case c.GetHeader("x-api-key") != "" && c.GetHeader("anthropic-version") != "":
controller.RetrieveModel(c, constant.ChannelTypeAnthropic)
default:
controller.RetrieveModel(c, constant.ChannelTypeOpenAI)
}
})
}
geminiRouter := router.Group("/v1beta/models")
geminiRouter.Use(middleware.RouteTag("relay"))
geminiRouter.Use(middleware.TokenAuth())
{
geminiRouter.GET("", func(c *gin.Context) {
controller.ListModels(c, constant.ChannelTypeGemini)
})
}
geminiCompatibleRouter := router.Group("/v1beta/openai/models")
geminiCompatibleRouter.Use(middleware.RouteTag("relay"))
geminiCompatibleRouter.Use(middleware.TokenAuth())
{
geminiCompatibleRouter.GET("", func(c *gin.Context) {
controller.ListModels(c, constant.ChannelTypeOpenAI)
})
}
playgroundRouter := router.Group("/pg")
playgroundRouter.Use(middleware.RouteTag("relay"))
playgroundRouter.Use(middleware.SystemPerformanceCheck())
playgroundRouter.Use(middleware.UserAuth(), middleware.Distribute())
{
playgroundRouter.POST("/chat/completions", controller.Playground)
}
relayV1Router := router.Group("/v1")
relayV1Router.Use(middleware.RouteTag("relay"))
relayV1Router.Use(middleware.SystemPerformanceCheck())
relayV1Router.Use(middleware.TokenAuth())
relayV1Router.Use(middleware.ModelRequestRateLimit())
{
// WebSocket 路由(统一到 Relay)
wsRouter := relayV1Router.Group("")
wsRouter.Use(middleware.Distribute())
wsRouter.GET("/realtime", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIRealtime)
})
}
{
//http router
httpRouter := relayV1Router.Group("")
httpRouter.Use(middleware.Distribute())
// claude related routes
// TODO: /messages/count_tokens is disabled. The current controller.CountClaudeTokens
// httpRouter.POST("/messages/count_tokens", controller.CountClaudeTokens)
httpRouter.POST("/messages", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatClaude)
})
// chat related routes
httpRouter.POST("/completions", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAI)
})
httpRouter.POST("/chat/completions", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAI)
})
// response related routes
httpRouter.POST("/responses/compact", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIResponsesCompaction)
})
// alpha search related routes (Codex standalone web search)
httpRouter.POST("/alpha/search", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIAlphaSearch)
})
// image related routes
httpRouter.POST("/edits", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIImage)
})
httpRouter.POST("/images/generations", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIImage)
})
httpRouter.POST("/images/edits", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIImage)
})
// embedding related routes
httpRouter.POST("/embeddings", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatEmbedding)
})
// audio related routes
httpRouter.POST("/audio/transcriptions", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIAudio)
})
httpRouter.POST("/audio/translations", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIAudio)
})
httpRouter.POST("/audio/speech", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAIAudio)
})
// rerank related routes
httpRouter.POST("/rerank", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatRerank)
})
// gemini relay routes
httpRouter.POST("/engines/:model/embeddings", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatGemini)
})
httpRouter.POST("/models/*path", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatGemini)
})
// other relay routes
httpRouter.POST("/moderations", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatOpenAI)
})
// not implemented
httpRouter.POST("/images/variations", controller.RelayNotImplemented)
httpRouter.GET("/files", controller.RelayNotImplemented)
httpRouter.POST("/files", controller.RelayNotImplemented)
httpRouter.DELETE("/files/:id", controller.RelayNotImplemented)
httpRouter.GET("/files/:id", controller.RelayNotImplemented)
httpRouter.GET("/files/:id/content", controller.RelayNotImplemented)
httpRouter.POST("/fine-tunes", controller.RelayNotImplemented)
httpRouter.GET("/fine-tunes", controller.RelayNotImplemented)
httpRouter.GET("/fine-tunes/:id", controller.RelayNotImplemented)
httpRouter.POST("/fine-tunes/:id/cancel", controller.RelayNotImplemented)
httpRouter.GET("/fine-tunes/:id/events", controller.RelayNotImplemented)
httpRouter.DELETE("/models/:model", controller.RelayNotImplemented)
}
relayMjRouter := router.Group("/mj")
relayMjRouter.Use(middleware.RouteTag("relay"))
relayMjRouter.Use(middleware.SystemPerformanceCheck())
registerMjRouterGroup(relayMjRouter)
relayMjModeRouter := router.Group("/:mode/mj")
relayMjModeRouter.Use(middleware.RouteTag("relay"))
relayMjModeRouter.Use(middleware.SystemPerformanceCheck())
registerMjRouterGroup(relayMjModeRouter)
//relayMjRouter.Use()
relayGeminiRouter := router.Group("/v1beta")
relayGeminiRouter.Use(middleware.RouteTag("relay"))
relayGeminiRouter.Use(middleware.SystemPerformanceCheck())
relayGeminiRouter.Use(middleware.TokenAuth())
relayGeminiRouter.Use(middleware.ModelRequestRateLimit())
relayGeminiRouter.Use(middleware.Distribute())
{
// Gemini API 路径格式: /v1beta/models/{model_name}:{action}
relayGeminiRouter.POST("/models/*path", func(c *gin.Context) {
controller.Relay(c, types.RelayFormatGemini)
})
}
}
func registerMjRouterGroup(relayMjRouter *gin.RouterGroup) {
relayMjRouter.GET("/image/:id", relay.RelayMidjourneyImage)
relayMjRouter.Use(middleware.TokenAuth(), middleware.Distribute())
{
relayMjRouter.POST("/submit/action", controller.RelayMidjourney)
relayMjRouter.POST("/submit/shorten", controller.RelayMidjourney)
relayMjRouter.POST("/submit/modal", controller.RelayMidjourney)
relayMjRouter.POST("/submit/imagine", controller.RelayMidjourney)
relayMjRouter.POST("/submit/change", controller.RelayMidjourney)
relayMjRouter.POST("/submit/simple-change", controller.RelayMidjourney)
relayMjRouter.POST("/submit/describe", controller.RelayMidjourney)
relayMjRouter.POST("/submit/blend", controller.RelayMidjourney)
relayMjRouter.POST("/submit/edits", controller.RelayMidjourney)
relayMjRouter.POST("/submit/video", controller.RelayMidjourney)
//relayMjRouter.POST("/notify", controller.RelayMidjourney)
relayMjRouter.GET("/task/:id/fetch", controller.RelayMidjourney)
relayMjRouter.GET("/task/:id/image-seed", controller.RelayMidjourney)
relayMjRouter.POST("/task/list-by-condition", controller.RelayMidjourney)
relayMjRouter.POST("/insight-face/swap", controller.RelayMidjourney)
relayMjRouter.POST("/submit/upload-discord-images", controller.RelayMidjourney)
}
}