Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

99 Zeilen
3.5 KiB

  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "github.com/QuantumNous/new-api/common"
  11. "github.com/QuantumNous/new-api/model"
  12. "github.com/QuantumNous/new-api/setting/system_setting"
  13. )
  14. type CompatibleAssetAdapter struct {
  15. name string
  16. operation map[AssetOperation]struct{}
  17. }
  18. func NewCompatibleAssetAdapter(name string, operations []AssetOperation) AssetAdapter {
  19. supported := make(map[AssetOperation]struct{}, len(operations))
  20. for _, op := range operations {
  21. supported[op] = struct{}{}
  22. }
  23. return &CompatibleAssetAdapter{name: name, operation: supported}
  24. }
  25. func (a *CompatibleAssetAdapter) Name() string {
  26. return a.name
  27. }
  28. func (a *CompatibleAssetAdapter) Supports(operation AssetOperation) bool {
  29. _, ok := a.operation[operation]
  30. return ok
  31. }
  32. func (a *CompatibleAssetAdapter) DoAssetRequest(ctx context.Context, channel *model.Channel, req AssetRequest) (*AssetUpstreamResponse, *AssetError) {
  33. if !a.Supports(req.Action.Operation) {
  34. return nil, newAssetError(AssetErrorOperationNotSupported, fmt.Sprintf("asset operation %s is not supported", req.Action.Operation), http.StatusBadRequest)
  35. }
  36. upstreamURL, err := buildCompatibleAssetURL(channel, req.Action.Action, req.Version)
  37. if err != nil {
  38. return nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  39. }
  40. fetchSetting := system_setting.GetFetchSetting()
  41. if err := common.ValidateURLWithFetchSetting(upstreamURL, fetchSetting.EnableSSRFProtection, fetchSetting.AllowPrivateIp, fetchSetting.DomainFilterMode, fetchSetting.IpFilterMode, fetchSetting.DomainList, fetchSetting.IpList, fetchSetting.AllowedPorts, fetchSetting.ApplyIPFilterForDomain); err != nil {
  42. return nil, newAssetError(AssetErrorServer, fmt.Sprintf("request blocked: %v", err), http.StatusForbidden)
  43. }
  44. httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, upstreamURL, bytes.NewReader(req.RawBody))
  45. if err != nil {
  46. return nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  47. }
  48. httpReq.Header.Set("Content-Type", "application/json")
  49. httpReq.Header.Set("Accept", "application/json")
  50. httpReq.Header.Set("Authorization", "Bearer "+strings.TrimSpace(channel.Key))
  51. client, err := GetHttpClientWithProxy(channel.GetSetting().Proxy)
  52. if err != nil {
  53. return nil, newAssetError(AssetErrorServer, err.Error(), http.StatusInternalServerError)
  54. }
  55. if client == nil {
  56. client = http.DefaultClient
  57. }
  58. resp, err := client.Do(httpReq)
  59. if err != nil {
  60. return nil, newAssetError(AssetErrorUpstream, err.Error(), http.StatusBadGateway)
  61. }
  62. defer resp.Body.Close()
  63. data, err := io.ReadAll(resp.Body)
  64. if err != nil {
  65. return nil, newAssetError(AssetErrorUpstream, err.Error(), http.StatusBadGateway)
  66. }
  67. if resp.StatusCode < 200 || resp.StatusCode >= 300 {
  68. return nil, newAssetError(AssetErrorUpstream, string(data), http.StatusBadGateway)
  69. }
  70. return &AssetUpstreamResponse{StatusCode: resp.StatusCode, Header: resp.Header, Body: data}, nil
  71. }
  72. func buildCompatibleAssetURL(channel *model.Channel, action string, version string) (string, error) {
  73. baseURL := strings.TrimSpace(channel.GetBaseURL())
  74. if baseURL == "" {
  75. baseURL = "https://ark.cn-beijing.volcengineapi.com"
  76. }
  77. u, err := url.Parse(baseURL)
  78. if err != nil {
  79. return "", err
  80. }
  81. u.Path = strings.TrimRight(u.Path, "/") + "/api/v1/multimodal/sd/assets"
  82. q := u.Query()
  83. q.Set("Action", action)
  84. if strings.TrimSpace(version) == "" {
  85. version = "2024-01-01"
  86. }
  87. q.Set("Version", version)
  88. u.RawQuery = q.Encode()
  89. return u.String(), nil
  90. }