refactor: Improve API header management via utility functions

This commit is contained in:
Aleksander Grygier 2025-11-26 15:36:09 +01:00
parent 9431f358b8
commit ddf98bdf28
4 changed files with 35 additions and 49 deletions

View File

@ -1,4 +1,5 @@
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { getJsonHeaders } from '$lib/utils/api-headers';
import { selectedModelName } from '$lib/stores/models.svelte'; import { selectedModelName } from '$lib/stores/models.svelte';
import { isRouterMode, propsStore } from '$lib/stores/props.svelte'; import { isRouterMode, propsStore } from '$lib/stores/props.svelte';
import type { import type {
@ -201,14 +202,9 @@ export class ChatService {
} }
try { try {
const apiKey = currentConfig.apiKey?.toString().trim();
const response = await fetch(`./v1/chat/completions`, { const response = await fetch(`./v1/chat/completions`, {
method: 'POST', method: 'POST',
headers: { headers: getJsonHeaders(),
'Content-Type': 'application/json',
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
},
body: JSON.stringify(requestBody), body: JSON.stringify(requestBody),
signal: abortController.signal signal: abortController.signal
}); });
@ -706,14 +702,8 @@ export class ChatService {
*/ */
static async getServerProps(): Promise<ApiLlamaCppServerProps> { static async getServerProps(): Promise<ApiLlamaCppServerProps> {
try { try {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
const response = await fetch(`./props`, { const response = await fetch(`./props`, {
headers: { headers: getJsonHeaders()
'Content-Type': 'application/json',
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
}
}); });
if (!response.ok) { if (!response.ok) {
@ -733,14 +723,8 @@ export class ChatService {
*/ */
static async getModels(): Promise<ApiModelListResponse> { static async getModels(): Promise<ApiModelListResponse> {
try { try {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
const response = await fetch(`./models`, { const response = await fetch(`./models`, {
headers: { headers: getJsonHeaders()
'Content-Type': 'application/json',
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
}
}); });
if (!response.ok) { if (!response.ok) {

View File

@ -1,6 +1,6 @@
import { base } from '$app/paths'; import { base } from '$app/paths';
import { config } from '$lib/stores/settings.svelte';
import { ServerModelStatus } from '$lib/enums'; import { ServerModelStatus } from '$lib/enums';
import { getJsonHeaders } from '$lib/utils/api-headers';
import type { import type {
ApiModelListResponse, ApiModelListResponse,
ApiModelDataEntry, ApiModelDataEntry,
@ -26,16 +26,6 @@ import type {
* - ModelsStore: Primary consumer for model state management * - ModelsStore: Primary consumer for model state management
*/ */
export class ModelsService { export class ModelsService {
private static getHeaders(): Record<string, string> {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
return {
'Content-Type': 'application/json',
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
};
}
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
// MODEL + ROUTER mode - OpenAI-compatible API // MODEL + ROUTER mode - OpenAI-compatible API
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@ -46,7 +36,7 @@ export class ModelsService {
*/ */
static async list(): Promise<ApiModelListResponse> { static async list(): Promise<ApiModelListResponse> {
const response = await fetch(`${base}/v1/models`, { const response = await fetch(`${base}/v1/models`, {
headers: this.getHeaders() headers: getJsonHeaders()
}); });
if (!response.ok) { if (!response.ok) {
@ -66,7 +56,7 @@ export class ModelsService {
*/ */
static async listRouter(): Promise<ApiRouterModelsListResponse> { static async listRouter(): Promise<ApiRouterModelsListResponse> {
const response = await fetch(`${base}/models`, { const response = await fetch(`${base}/models`, {
headers: this.getHeaders() headers: getJsonHeaders()
}); });
if (!response.ok) { if (!response.ok) {
@ -90,7 +80,7 @@ export class ModelsService {
const response = await fetch(`${base}/models/load`, { const response = await fetch(`${base}/models/load`, {
method: 'POST', method: 'POST',
headers: this.getHeaders(), headers: getJsonHeaders(),
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
@ -110,7 +100,7 @@ export class ModelsService {
static async unload(modelId: string): Promise<ApiRouterModelsUnloadResponse> { static async unload(modelId: string): Promise<ApiRouterModelsUnloadResponse> {
const response = await fetch(`${base}/models/unload`, { const response = await fetch(`${base}/models/unload`, {
method: 'POST', method: 'POST',
headers: this.getHeaders(), headers: getJsonHeaders(),
body: JSON.stringify({ model: modelId }) body: JSON.stringify({ model: modelId })
}); });
@ -128,7 +118,7 @@ export class ModelsService {
*/ */
static async getStatus(modelId: string): Promise<ApiRouterModelsStatusResponse> { static async getStatus(modelId: string): Promise<ApiRouterModelsStatusResponse> {
const response = await fetch(`${base}/models/status?model=${encodeURIComponent(modelId)}`, { const response = await fetch(`${base}/models/status?model=${encodeURIComponent(modelId)}`, {
headers: this.getHeaders() headers: getJsonHeaders()
}); });
if (!response.ok) { if (!response.ok) {

View File

@ -1,4 +1,4 @@
import { config } from '$lib/stores/settings.svelte'; import { getAuthHeaders } from '$lib/utils/api-headers';
/** /**
* PropsService - Server properties management * PropsService - Server properties management
@ -22,13 +22,8 @@ export class PropsService {
* @throws {Error} If the request fails or returns invalid data * @throws {Error} If the request fails or returns invalid data
*/ */
static async fetch(): Promise<ApiLlamaCppServerProps> { static async fetch(): Promise<ApiLlamaCppServerProps> {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
const response = await fetch('./props', { const response = await fetch('./props', {
headers: { headers: getAuthHeaders()
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
}
}); });
if (!response.ok) { if (!response.ok) {
@ -49,16 +44,11 @@ export class PropsService {
* @throws {Error} If the request fails or returns invalid data * @throws {Error} If the request fails or returns invalid data
*/ */
static async fetchForModel(modelId: string): Promise<ApiLlamaCppServerProps> { static async fetchForModel(modelId: string): Promise<ApiLlamaCppServerProps> {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
const url = new URL('./props', window.location.href); const url = new URL('./props', window.location.href);
url.searchParams.set('model', modelId); url.searchParams.set('model', modelId);
const response = await fetch(url.toString(), { const response = await fetch(url.toString(), {
headers: { headers: getAuthHeaders()
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {})
}
}); });
if (!response.ok) { if (!response.ok) {

View File

@ -0,0 +1,22 @@
import { config } from '$lib/stores/settings.svelte';
/**
* Get authorization headers for API requests
* Includes Bearer token if API key is configured
*/
export function getAuthHeaders(): Record<string, string> {
const currentConfig = config();
const apiKey = currentConfig.apiKey?.toString().trim();
return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
}
/**
* Get standard JSON headers with optional authorization
*/
export function getJsonHeaders(): Record<string, string> {
return {
'Content-Type': 'application/json',
...getAuthHeaders()
};
}