From 1623fd77388c8660c53d27d687baebc1d630f73f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 12:23:00 +0000 Subject: [PATCH] Investigate CORS proxy failure The CORS proxy is failing despite being enabled, resulting in REST API and database connection errors. Investigate the cause of the failure. --- src/lib/supabase/client.ts | 27 +++++++++++++++-------- src/lib/supabase/config.ts | 12 +++++++---- src/lib/supabase/tests.ts | 6 +++++- src/pages/SupabaseSettings.tsx | 39 ++++++++++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/lib/supabase/client.ts b/src/lib/supabase/client.ts index 3d46105..56870e9 100644 --- a/src/lib/supabase/client.ts +++ b/src/lib/supabase/client.ts @@ -24,16 +24,25 @@ try { flowType: 'implicit', }, global: { - fetch: (url, options) => { - // CORS 디버깅을 위한 사용자 정의 fetch + // 커스텀 fetch 구현 + fetch: (...args) => { + // 첫 번째 인자는 URL 또는 Request 객체 + const urlOrRequest = args[0]; + + // URL 로깅 및 디버깅 + let url = typeof urlOrRequest === 'string' ? urlOrRequest : urlOrRequest.url; console.log('Supabase fetch 요청:', url); - return fetch(url, options).then(response => { - console.log('Supabase 응답 상태:', response.status); - return response; - }).catch(err => { - console.error('Supabase fetch 오류:', err); - throw err; - }); + + // 기본 fetch 호출 + return fetch(...args) + .then(response => { + console.log('Supabase 응답 상태:', response.status); + return response; + }) + .catch(err => { + console.error('Supabase fetch 오류:', err); + throw err; + }); } } }); diff --git a/src/lib/supabase/config.ts b/src/lib/supabase/config.ts index aedbf15..1041a6b 100644 --- a/src/lib/supabase/config.ts +++ b/src/lib/supabase/config.ts @@ -6,9 +6,10 @@ export const getSupabaseUrl = () => { if (storedUrl) { // CORS 프록시 설정 확인 const useProxy = localStorage.getItem('use_cors_proxy') === 'true'; - if (useProxy && storedUrl.startsWith('http://')) { - // CORS 프록시 URL로 변환 - return `https://corsproxy.io/?${encodeURIComponent(storedUrl)}`; + if (useProxy) { + // CORS 프록시 URL로 변환 (URL 구조 개선) + const cleanUrl = storedUrl.trim(); + return `https://corsproxy.io/?${encodeURIComponent(cleanUrl)}`; } return storedUrl; } @@ -39,8 +40,11 @@ export const isCorsProxyEnabled = () => { // 온프레미스 연결을 위한 설정 도우미 함수 export const configureSupabase = (url: string, key: string, useProxy: boolean = false) => { + // URL 정리 (앞뒤 공백 제거) + const cleanUrl = url.trim(); + // 로컬 스토리지에 설정 저장 - localStorage.setItem('supabase_url', url); + localStorage.setItem('supabase_url', cleanUrl); localStorage.setItem('supabase_key', key); localStorage.setItem('use_cors_proxy', useProxy.toString()); diff --git a/src/lib/supabase/tests.ts b/src/lib/supabase/tests.ts index d772fd7..c9cc6aa 100644 --- a/src/lib/supabase/tests.ts +++ b/src/lib/supabase/tests.ts @@ -42,7 +42,11 @@ export const testSupabaseConnection = async () => { // 1. REST API 접근 테스트 try { console.log('REST API 테스트 시작...'); - const apiUrl = `${results.proxyUrl}/rest/v1/`; + // 정확한 REST API 엔드포인트 구성 + const apiUrl = results.proxyUrl.endsWith('/') + ? `${results.proxyUrl}rest/v1/` + : `${results.proxyUrl}/rest/v1/`; + console.log('REST API 테스트 URL:', apiUrl); const response = await fetch(apiUrl, { diff --git a/src/pages/SupabaseSettings.tsx b/src/pages/SupabaseSettings.tsx index 38c3b35..4e71824 100644 --- a/src/pages/SupabaseSettings.tsx +++ b/src/pages/SupabaseSettings.tsx @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; -import { DatabaseIcon, Save, RefreshCw, Shield } from "lucide-react"; +import { DatabaseIcon, Save, RefreshCw, Shield, AlertTriangle, Check } from "lucide-react"; import { toast } from "@/hooks/useToast.wrapper"; import { configureSupabase, isCorsProxyEnabled } from "@/lib/supabase/config"; import { Switch } from "@/components/ui/switch"; @@ -29,6 +29,11 @@ const SupabaseSettings = () => { setUseProxy(proxyEnabled); }, []); + const validateUrl = (url: string): boolean => { + // URL 유효성 검사: http:// 또는 https://로 시작하는지 확인 + return /^https?:\/\/.+/.test(url); + }; + const handleSave = () => { if (!supabaseUrl || !supabaseKey) { toast({ @@ -39,6 +44,15 @@ const SupabaseSettings = () => { return; } + if (!validateUrl(supabaseUrl)) { + toast({ + title: "URL 오류", + description: "유효한 URL 형식이 아닙니다. http:// 또는 https://로 시작하는 URL을 입력해주세요.", + variant: "destructive" + }); + return; + } + setIsSaving(true); try { @@ -90,6 +104,9 @@ const SupabaseSettings = () => { } }; + const isHttpsUrl = supabaseUrl.startsWith("https://"); + const suggestProxy = supabaseUrl.startsWith("http://") && !useProxy; + return (