2023-04-23 18:24:11 +08:00
|
|
|
|
package router
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-08-10 11:36:26 +08:00
|
|
|
|
"one-api/constant"
|
2023-04-23 18:24:11 +08:00
|
|
|
|
"one-api/controller"
|
|
|
|
|
|
"one-api/middleware"
|
2024-02-29 01:08:18 +08:00
|
|
|
|
"one-api/relay"
|
2025-08-14 20:05:06 +08:00
|
|
|
|
"one-api/types"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2023-04-23 18:24:11 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func SetRelayRouter(router *gin.Engine) {
|
2023-09-17 11:44:38 +08:00
|
|
|
|
router.Use(middleware.CORS())
|
2024-12-04 23:53:02 +08:00
|
|
|
|
router.Use(middleware.DecompressRequestMiddleware())
|
2025-06-10 19:29:32 +08:00
|
|
|
|
router.Use(middleware.StatsMiddleware())
|
2023-04-28 16:58:55 +08:00
|
|
|
|
// https://platform.openai.com/docs/api-reference/introduction
|
2023-06-07 23:26:00 +08:00
|
|
|
|
modelsRouter := router.Group("/v1/models")
|
|
|
|
|
|
modelsRouter.Use(middleware.TokenAuth())
|
|
|
|
|
|
{
|
2025-08-10 11:36:26 +08:00
|
|
|
|
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.RetrieveModel(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)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2023-06-07 23:26:00 +08:00
|
|
|
|
}
|
2025-08-10 11:36:26 +08:00
|
|
|
|
|
|
|
|
|
|
geminiRouter := router.Group("/v1beta/models")
|
|
|
|
|
|
geminiRouter.Use(middleware.TokenAuth())
|
|
|
|
|
|
{
|
|
|
|
|
|
geminiRouter.GET("", func(c *gin.Context) {
|
|
|
|
|
|
controller.ListModels(c, constant.ChannelTypeGemini)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
geminiCompatibleRouter := router.Group("/v1beta/openai/models")
|
|
|
|
|
|
geminiCompatibleRouter.Use(middleware.TokenAuth())
|
|
|
|
|
|
{
|
|
|
|
|
|
geminiCompatibleRouter.GET("", func(c *gin.Context) {
|
|
|
|
|
|
controller.ListModels(c, constant.ChannelTypeOpenAI)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-26 00:59:09 +08:00
|
|
|
|
playgroundRouter := router.Group("/pg")
|
2025-07-06 12:37:56 +08:00
|
|
|
|
playgroundRouter.Use(middleware.UserAuth(), middleware.Distribute())
|
2024-09-26 00:59:09 +08:00
|
|
|
|
{
|
|
|
|
|
|
playgroundRouter.POST("/chat/completions", controller.Playground)
|
|
|
|
|
|
}
|
2023-04-25 22:18:27 +08:00
|
|
|
|
relayV1Router := router.Group("/v1")
|
2024-10-03 20:46:00 +08:00
|
|
|
|
relayV1Router.Use(middleware.TokenAuth())
|
2025-02-24 16:20:55 +08:00
|
|
|
|
relayV1Router.Use(middleware.ModelRequestRateLimit())
|
2023-04-23 18:24:11 +08:00
|
|
|
|
{
|
2025-08-14 20:05:06 +08:00
|
|
|
|
// WebSocket 路由(统一到 Relay)
|
2024-10-03 20:46:00 +08:00
|
|
|
|
wsRouter := relayV1Router.Group("")
|
|
|
|
|
|
wsRouter.Use(middleware.Distribute())
|
2025-08-14 20:05:06 +08:00
|
|
|
|
wsRouter.GET("/realtime", func(c *gin.Context) {
|
|
|
|
|
|
controller.Relay(c, types.RelayFormatOpenAIRealtime)
|
|
|
|
|
|
})
|
2024-10-03 20:46:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
//http router
|
|
|
|
|
|
httpRouter := relayV1Router.Group("")
|
|
|
|
|
|
httpRouter.Use(middleware.Distribute())
|
2025-08-14 20:05:06 +08:00
|
|
|
|
|
|
|
|
|
|
// claude related routes
|
|
|
|
|
|
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", func(c *gin.Context) {
|
|
|
|
|
|
controller.Relay(c, types.RelayFormatOpenAIResponses)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
2024-10-03 20:46:00 +08:00
|
|
|
|
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)
|
2023-04-25 22:18:27 +08:00
|
|
|
|
}
|
2024-03-29 16:48:50 +08:00
|
|
|
|
|
2023-08-14 22:16:32 +08:00
|
|
|
|
relayMjRouter := router.Group("/mj")
|
2024-03-29 16:48:50 +08:00
|
|
|
|
registerMjRouterGroup(relayMjRouter)
|
|
|
|
|
|
|
|
|
|
|
|
relayMjModeRouter := router.Group("/:mode/mj")
|
|
|
|
|
|
registerMjRouterGroup(relayMjModeRouter)
|
|
|
|
|
|
//relayMjRouter.Use()
|
2024-06-12 20:37:42 +08:00
|
|
|
|
|
|
|
|
|
|
relaySunoRouter := router.Group("/suno")
|
|
|
|
|
|
relaySunoRouter.Use(middleware.TokenAuth(), middleware.Distribute())
|
|
|
|
|
|
{
|
|
|
|
|
|
relaySunoRouter.POST("/submit/:action", controller.RelayTask)
|
|
|
|
|
|
relaySunoRouter.POST("/fetch", controller.RelayTask)
|
|
|
|
|
|
relaySunoRouter.GET("/fetch/:id", controller.RelayTask)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-26 13:34:41 +08:00
|
|
|
|
relayGeminiRouter := router.Group("/v1beta")
|
|
|
|
|
|
relayGeminiRouter.Use(middleware.TokenAuth())
|
|
|
|
|
|
relayGeminiRouter.Use(middleware.ModelRequestRateLimit())
|
|
|
|
|
|
relayGeminiRouter.Use(middleware.Distribute())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Gemini API 路径格式: /v1beta/models/{model_name}:{action}
|
2025-08-14 20:05:06 +08:00
|
|
|
|
relayGeminiRouter.POST("/models/*path", func(c *gin.Context) {
|
|
|
|
|
|
controller.Relay(c, types.RelayFormatGemini)
|
|
|
|
|
|
})
|
2025-05-26 13:34:41 +08:00
|
|
|
|
}
|
2024-03-29 16:48:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func registerMjRouterGroup(relayMjRouter *gin.RouterGroup) {
|
2024-02-29 01:08:18 +08:00
|
|
|
|
relayMjRouter.GET("/image/:id", relay.RelayMidjourneyImage)
|
2023-08-14 22:16:32 +08:00
|
|
|
|
relayMjRouter.Use(middleware.TokenAuth(), middleware.Distribute())
|
|
|
|
|
|
{
|
2024-03-13 15:37:01 +08:00
|
|
|
|
relayMjRouter.POST("/submit/action", controller.RelayMidjourney)
|
2024-03-13 17:46:34 +08:00
|
|
|
|
relayMjRouter.POST("/submit/shorten", controller.RelayMidjourney)
|
2024-03-13 15:37:01 +08:00
|
|
|
|
relayMjRouter.POST("/submit/modal", controller.RelayMidjourney)
|
2023-08-14 22:16:32 +08:00
|
|
|
|
relayMjRouter.POST("/submit/imagine", controller.RelayMidjourney)
|
|
|
|
|
|
relayMjRouter.POST("/submit/change", controller.RelayMidjourney)
|
2024-01-01 22:46:05 +08:00
|
|
|
|
relayMjRouter.POST("/submit/simple-change", controller.RelayMidjourney)
|
2023-11-14 08:55:45 +08:00
|
|
|
|
relayMjRouter.POST("/submit/describe", controller.RelayMidjourney)
|
|
|
|
|
|
relayMjRouter.POST("/submit/blend", controller.RelayMidjourney)
|
2025-06-30 22:31:12 +08:00
|
|
|
|
relayMjRouter.POST("/submit/edits", controller.RelayMidjourney)
|
|
|
|
|
|
relayMjRouter.POST("/submit/video", controller.RelayMidjourney)
|
2023-08-14 22:16:32 +08:00
|
|
|
|
relayMjRouter.POST("/notify", controller.RelayMidjourney)
|
|
|
|
|
|
relayMjRouter.GET("/task/:id/fetch", controller.RelayMidjourney)
|
2024-03-14 16:42:37 +08:00
|
|
|
|
relayMjRouter.GET("/task/:id/image-seed", controller.RelayMidjourney)
|
2024-01-01 22:46:05 +08:00
|
|
|
|
relayMjRouter.POST("/task/list-by-condition", controller.RelayMidjourney)
|
2024-03-14 18:08:12 +08:00
|
|
|
|
relayMjRouter.POST("/insight-face/swap", controller.RelayMidjourney)
|
2024-07-31 15:48:51 +08:00
|
|
|
|
relayMjRouter.POST("/submit/upload-discord-images", controller.RelayMidjourney)
|
2023-08-14 22:16:32 +08:00
|
|
|
|
}
|
2023-04-23 18:24:11 +08:00
|
|
|
|
}
|