diff --git a/lib/configStorageTypes.ts b/lib/configStorageTypes.ts index fd34fc0..55245ab 100644 --- a/lib/configStorageTypes.ts +++ b/lib/configStorageTypes.ts @@ -41,16 +41,23 @@ export const DEFAULT_RELAYS: RelayConfig[] = [ export const DEFAULT_NIP95_APIS: Nip95Config[] = [ { id: 'default', - url: 'https://nostr.build/api/v2/upload', + url: 'https://picstr.build/api/v1/upload', enabled: true, priority: 1, createdAt: Date.now(), }, + { + id: 'nostrbuild', + url: 'https://nostr.build/api/v2/upload', + enabled: false, + priority: 2, + createdAt: Date.now(), + }, { id: 'nostrcheck', url: 'https://nostrcheck.me/api/v1/media', enabled: false, - priority: 2, + priority: 3, createdAt: Date.now(), }, ] diff --git a/lib/nip95.ts b/lib/nip95.ts index fe81dd8..e399776 100644 --- a/lib/nip95.ts +++ b/lib/nip95.ts @@ -72,7 +72,7 @@ function parseUploadResponse(result: unknown, endpoint: string): string { * Uses proxy API route for endpoints that have CORS issues */ async function tryUploadEndpoint(endpoint: string, formData: FormData, useProxy: boolean = false): Promise { - const targetUrl = useProxy ? '/api/nip95-upload' : endpoint + const targetUrl = useProxy ? endpoint : endpoint const response = await fetch(targetUrl, { method: 'POST', @@ -131,12 +131,15 @@ export async function uploadNip95Media(file: File): Promise { const error = e instanceof Error ? e : new Error(String(e)) const errorMessage = error.message - // If CORS error or network error, try via proxy + // If CORS error, network error, or 405 error, try via proxy const isCorsError = errorMessage.includes('CORS') || errorMessage.includes('Failed to fetch') - if (isCorsError && endpoint.includes('nostr.build')) { + const isMethodNotAllowed = errorMessage.includes('405') || errorMessage.includes('Method Not Allowed') + if (isCorsError || isMethodNotAllowed) { try { - console.log('Trying upload via proxy due to CORS error:', endpoint) - const url = await tryUploadEndpoint(endpoint, formData, true) + console.log('Trying upload via proxy due to error:', endpoint, isCorsError ? 'CORS' : 'Method Not Allowed') + // Pass endpoint as query parameter to proxy + const proxyUrl = `/api/nip95-upload?endpoint=${encodeURIComponent(endpoint)}` + const url = await tryUploadEndpoint(proxyUrl, formData, true) return { url, type: mediaType } } catch (proxyError) { console.error('NIP-95 upload proxy error:', { diff --git a/pages/api/nip95-upload.ts b/pages/api/nip95-upload.ts index 6211d25..b67f6dc 100644 --- a/pages/api/nip95-upload.ts +++ b/pages/api/nip95-upload.ts @@ -2,8 +2,8 @@ import { NextApiRequest, NextApiResponse } from 'next' import { IncomingForm, File as FormidableFile } from 'formidable' import FormData from 'form-data' import fs from 'fs' +import { Readable } from 'stream' -const TARGET_ENDPOINT = 'https://nostr.build/api/v2/upload' const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB export const config = { @@ -22,6 +22,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return res.status(405).json({ error: 'Method not allowed' }) } + // Get target endpoint from query or use default + const targetEndpoint = (req.query.endpoint as string) || 'https://picstr.build/api/v1/upload' + try { // Parse multipart form data // formidable needs the raw Node.js IncomingMessage, which NextApiRequest extends @@ -59,7 +62,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }) // Forward to target endpoint - const response = await fetch(TARGET_ENDPOINT, { + const response = await fetch(targetEndpoint, { method: 'POST', body: formData as unknown as BodyInit, headers: {