Add Harbor fallback for catalog and search endpoints

Harbor denies access to the V2 _catalog endpoint for robot accounts
(scope registry:catalog:* returns an empty JWT). This adds automatic
Harbor detection and falls back to the native Harbor project API
(/api/v2.0/projects/{name}/repositories) for both catalog listing
and image search.

- Detect Harbor via WWW-Authenticate header + /api/v2.0/ping (cached 5min)
- List repositories through Harbor project API with pagination
- Search repositories using Harbor's q=name=~ filter
- Transparent fallback: no configuration change required

Fixes #360

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Pascal GUINETandClaude Opus 4.6 authored and Jarek Krochmalski committed 2026-06-16 09:08:46 +02:00
1 parent 83c3a5ea09
commit eb5cf32d68
3 files changed
+246 -2

No files matched your search

+7 -1
View File
@@ -1,7 +1,7 @@
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getRegistry } from '$lib/server/db';
import { getRegistryAuth, parseRegistryUrl } from '$lib/server/docker';
import { getRegistryAuth, isHarborRegistry, harborSearchRepositories, parseRegistryUrl } from '$lib/server/docker';
interface SearchResult {
name: string;
@@ -127,6 +127,12 @@ async function tryDirectImageLookup(registry: any, imageName: string): Promise<b
// Search through catalog (slow for large registries, limited to first few pages)
async function searchCatalog(registry: any, term: string, limit: number): Promise<string[]> {
// Fallback Harbor : utiliser l'API projet native pour la recherche
if (await isHarborRegistry(registry.url)) {
const { path: orgPath } = parseRegistryUrl(registry.url);
return harborSearchRepositories(registry, term, orgPath, limit);
}
// Note: orgPath could be used here to filter results, but search is already term-based
const { baseUrl, authHeader } = await getRegistryAuth(registry, 'registry:catalog:*');