Replace url.origin with trimTrailingSlash (#4118) * Replace url.origin with trimV1 * Replace url.origin with trimTrailingSlash
Signed| @@ -16,6 +16,7 @@ import { | ||
| 16 | 16 | mergeObjectWithYaml, |
| 17 | 17 | excludeKeysByYaml, |
| 18 | 18 | color, |
| 19 | + trimTrailingSlash, | |
| 19 | 20 | } from '../../util.js'; |
| 20 | 21 | import { |
| 21 | 22 | convertClaudeMessages, |
| @@ -1094,11 +1095,11 @@ router.post('/status', async function (request, statusResponse) { | ||
| 1094 | 1095 | headers = {}; |
| 1095 | 1096 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) { |
| 1096 | 1097 | apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE); |
| 1097 | 1098 | apiUrl = new URLtrimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE); |
| 1098 | 1099 | const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta'); |
| 1099 | 1100 | const modelsUrl = !apiKey && request.body.reverse_proxy |
| 1100 | 1101 | ? `${apiUrl.origin}/${apiVersion}/models` |
| 1101 | 1102 | : `${apiUrl.origin}/${apiVersion}/models?key=${apiKey}`; |
| 1102 | 1103 | |
| 1103 | 1104 | if (!apiKey && !request.body.reverse_proxy) { |
| 1104 | 1105 | console.warn('Google AI Studio API key is missing.'); |
| @@ -6,6 +6,7 @@ import crypto from 'node:crypto'; | ||
| 6 | 6 | |
| 7 | 7 | import { readSecret, SECRET_KEYS } from './secrets.js'; |
| 8 | 8 | import { GEMINI_SAFETY } from '../constants.js'; |
| 9 | +import { trimTrailingSlash } from '../util.js'; | |
| 9 | 10 | |
| 10 | 11 | const API_MAKERSUITE = 'https://generativelanguage.googleapis.com'; |
| 11 | 12 | const API_VERTEX_AI = 'https://us-central1-aiplatform.googleapis.com'; |
| @@ -148,8 +149,8 @@ router.post('/caption-image', async (request, response) => { | ||
| 148 | 149 | if (authType === 'express') { |
| 149 | 150 | // Express mode: use API key parameter |
| 150 | 151 | const keyParam = authHeader.replace('Bearer ', ''); |
| 151 | 152 | const apiUrl = new URLtrimTrailingSlash(request.body.reverse_proxy || API_VERTEX_AI); |
| 152 | 153 | url = `${apiUrl.origin}/v1/publishers/google/models/${model}:generateContent?key=${keyParam}`; |
| 153 | 154 | } else if (authType === 'full') { |
| 154 | 155 | // Full mode: use project-specific URL with Authorization header |
| 155 | 156 | // Get project ID from Service Account JSON |
| @@ -177,15 +178,15 @@ router.post('/caption-image', async (request, response) => { | ||
| 177 | 178 | headers['Authorization'] = authHeader; |
| 178 | 179 | } else { |
| 179 | 180 | // Proxy mode: use Authorization header |
| 180 | 181 | const apiUrl = new URLtrimTrailingSlash(request.body.reverse_proxy || API_VERTEX_AI); |
| 181 | 182 | url = `${apiUrl.origin}/v1/publishers/google/models/${model}:generateContent`; |
| 182 | 183 | headers['Authorization'] = authHeader; |
| 183 | 184 | } |
| 184 | 185 | } else { |
| 185 | 186 | // Google AI Studio |
| 186 | 187 | const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE); |
| 187 | 188 | const apiUrl = new URLtrimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE); |
| 188 | 189 | url = `${apiUrl.origin}/v1beta/models/${model}:generateContent?key=${apiKey}`; |
| 189 | 190 | } |
| 190 | 191 | const body = { |
| 191 | 192 | contents: [{ |
| @@ -659,6 +659,15 @@ export function trimV1(str) { | ||
| 659 | 659 | } |
| 660 | 660 | |
| 661 | 661 | /** |
| 662 | + * Removes trailing slash from a string. | |
| 663 | + * @param {string} str Input string | |
| 664 | + * @returns {string} String with trailing slash removed | |
| 665 | + */ | |
| 666 | +export function trimTrailingSlash(str) { | |
| 667 | + return String(str ?? '').replace(/\/$/, ''); | |
| 668 | +} | |
| 669 | + | |
| 670 | +/** | |
| 662 | 671 | * Simple TTL memory cache. |
| 663 | 672 | */ |
| 664 | 673 | export class Cache { |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | import fetch from 'node-fetch'; |
| 2 | 2 | import { SECRET_KEYS, readSecret } from '../endpoints/secrets.js'; |
| 3 | +import { trimTrailingSlash } from '../util.js'; | |
| 3 | 4 | const API_MAKERSUITE = 'https://generativelanguage.googleapis.com'; |
| 4 | 5 | |
| 5 | 6 | /** |
| @@ -27,9 +28,9 @@ export async function getMakerSuiteVector(text, directories) { | ||
| 27 | 28 | throw new Error('No Google AI Studio key found'); |
| 28 | 29 | } |
| 29 | 30 | |
| 30 | 31 | const apiUrl = new URLtrimTrailingSlash(API_MAKERSUITE); |
| 31 | 32 | const model = 'text-embedding-004'; |
| 32 | 33 | const url = `${apiUrl.origin}/v1beta/models/${model}:embedContent?key=${key}`; |
| 33 | 34 | const body = { |
| 34 | 35 | content: { |
| 35 | 36 | parts: [ |