| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- package controller
- import (
- "fmt"
- "net/http"
- "strings"
- "github.com/QuantumNous/new-api/common"
- "github.com/QuantumNous/new-api/constant"
- "github.com/QuantumNous/new-api/logger"
- "github.com/QuantumNous/new-api/relay/channel/gemini"
- "github.com/gin-gonic/gin"
- )
- // RelayGeminiFileUpload handles file upload to Gemini File API
- func RelayGeminiFileUpload(c *gin.Context) {
- // Parse multipart form
- form, err := common.ParseMultipartFormReusable(c)
- if err != nil {
- logger.LogError(c, fmt.Sprintf("failed to parse multipart form: %s", err.Error()))
- c.JSON(http.StatusBadRequest, gin.H{
- "error": gin.H{
- "message": fmt.Sprintf("failed to parse multipart form: %s", err.Error()),
- "type": "invalid_request_error",
- "code": "invalid_multipart_form",
- },
- })
- return
- }
- defer form.RemoveAll()
- // Get API key from channel context (set by setupGeminiFileChannel)
- apiKey := common.GetContextKeyString(c, constant.ContextKeyChannelKey)
- if apiKey == "" {
- logger.LogError(c, "Failed to get Gemini channel API key")
- c.JSON(http.StatusServiceUnavailable, gin.H{
- "error": gin.H{
- "message": "No available Gemini channel found",
- "type": "service_unavailable_error",
- "code": "no_available_channel",
- },
- })
- return
- }
- // Rebuild multipart form for upstream request
- body, contentType, err := gemini.RebuildMultipartForm(form)
- if err != nil {
- logger.LogError(c, fmt.Sprintf("failed to rebuild multipart form: %s", err.Error()))
- c.JSON(http.StatusInternalServerError, gin.H{
- "error": gin.H{
- "message": fmt.Sprintf("failed to rebuild multipart form: %s", err.Error()),
- "type": "internal_error",
- "code": "form_rebuild_error",
- },
- })
- return
- }
- // Build upstream URL
- url := gemini.BuildGeminiFileURL("/upload/v1beta/files")
- // Prepare headers
- headers := map[string]string{
- "Content-Type": contentType,
- "x-goog-api-key": apiKey,
- }
- // Forward request to Gemini
- err = gemini.ForwardGeminiFileRequest(c, http.MethodPost, url, body, headers)
- if err != nil {
- logger.LogError(c, fmt.Sprintf("failed to forward file upload request: %s", err.Error()))
- // Error response already sent by ForwardGeminiFileRequest
- return
- }
- }
- // RelayGeminiFileList lists files from Gemini File API
- func RelayGeminiFileList(c *gin.Context) {
- // Get API key from channel context
- apiKey := common.GetContextKeyString(c, constant.ContextKeyChannelKey)
- if apiKey == "" {
- logger.LogError(c, "API key not found in context")
- c.JSON(http.StatusUnauthorized, gin.H{
- "error": gin.H{
- "message": "API key not found",
- "type": "authentication_error",
- "code": "invalid_api_key",
- },
- })
- return
- }
- // Build upstream URL with query parameters
- url := gemini.BuildGeminiFileURL("/v1beta/files")
- // Add query parameters if present
- queryParams := []string{}
- if pageSize := c.Query("pageSize"); pageSize != "" {
- queryParams = append(queryParams, fmt.Sprintf("pageSize=%s", pageSize))
- }
- if pageToken := c.Query("pageToken"); pageToken != "" {
- queryParams = append(queryParams, fmt.Sprintf("pageToken=%s", pageToken))
- }
- if len(queryParams) > 0 {
- url = fmt.Sprintf("%s?%s", url, strings.Join(queryParams, "&"))
- }
- // Prepare headers
- headers := map[string]string{
- "x-goog-api-key": apiKey,
- }
- // Forward request to Gemini
- err := gemini.ForwardGeminiFileRequest(c, http.MethodGet, url, nil, headers)
- if err != nil {
- logger.LogError(c, fmt.Sprintf("failed to forward file list request: %s", err.Error()))
- return
- }
- }
|