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.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 12:23:00 +00:00
parent 893e1cf0aa
commit 1623fd7738
4 changed files with 68 additions and 16 deletions

View File

@@ -24,16 +24,25 @@ try {
flowType: 'implicit', flowType: 'implicit',
}, },
global: { global: {
fetch: (url, options) => { // 커스텀 fetch 구현
// CORS 디버깅을 위한 사용자 정의 fetch fetch: (...args) => {
// 첫 번째 인자는 URL 또는 Request 객체
const urlOrRequest = args[0];
// URL 로깅 및 디버깅
let url = typeof urlOrRequest === 'string' ? urlOrRequest : urlOrRequest.url;
console.log('Supabase fetch 요청:', url); console.log('Supabase fetch 요청:', url);
return fetch(url, options).then(response => {
console.log('Supabase 응답 상태:', response.status); // 기본 fetch 호출
return response; return fetch(...args)
}).catch(err => { .then(response => {
console.error('Supabase fetch 오류:', err); console.log('Supabase 응답 상태:', response.status);
throw err; return response;
}); })
.catch(err => {
console.error('Supabase fetch 오류:', err);
throw err;
});
} }
} }
}); });

View File

@@ -6,9 +6,10 @@ export const getSupabaseUrl = () => {
if (storedUrl) { if (storedUrl) {
// CORS 프록시 설정 확인 // CORS 프록시 설정 확인
const useProxy = localStorage.getItem('use_cors_proxy') === 'true'; const useProxy = localStorage.getItem('use_cors_proxy') === 'true';
if (useProxy && storedUrl.startsWith('http://')) { if (useProxy) {
// CORS 프록시 URL로 변환 // CORS 프록시 URL로 변환 (URL 구조 개선)
return `https://corsproxy.io/?${encodeURIComponent(storedUrl)}`; const cleanUrl = storedUrl.trim();
return `https://corsproxy.io/?${encodeURIComponent(cleanUrl)}`;
} }
return storedUrl; return storedUrl;
} }
@@ -39,8 +40,11 @@ export const isCorsProxyEnabled = () => {
// 온프레미스 연결을 위한 설정 도우미 함수 // 온프레미스 연결을 위한 설정 도우미 함수
export const configureSupabase = (url: string, key: string, useProxy: boolean = false) => { 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('supabase_key', key);
localStorage.setItem('use_cors_proxy', useProxy.toString()); localStorage.setItem('use_cors_proxy', useProxy.toString());

View File

@@ -42,7 +42,11 @@ export const testSupabaseConnection = async () => {
// 1. REST API 접근 테스트 // 1. REST API 접근 테스트
try { try {
console.log('REST API 테스트 시작...'); 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); console.log('REST API 테스트 URL:', apiUrl);
const response = await fetch(apiUrl, { const response = await fetch(apiUrl, {

View File

@@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label"; 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 { toast } from "@/hooks/useToast.wrapper";
import { configureSupabase, isCorsProxyEnabled } from "@/lib/supabase/config"; import { configureSupabase, isCorsProxyEnabled } from "@/lib/supabase/config";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
@@ -29,6 +29,11 @@ const SupabaseSettings = () => {
setUseProxy(proxyEnabled); setUseProxy(proxyEnabled);
}, []); }, []);
const validateUrl = (url: string): boolean => {
// URL 유효성 검사: http:// 또는 https://로 시작하는지 확인
return /^https?:\/\/.+/.test(url);
};
const handleSave = () => { const handleSave = () => {
if (!supabaseUrl || !supabaseKey) { if (!supabaseUrl || !supabaseKey) {
toast({ toast({
@@ -39,6 +44,15 @@ const SupabaseSettings = () => {
return; return;
} }
if (!validateUrl(supabaseUrl)) {
toast({
title: "URL 오류",
description: "유효한 URL 형식이 아닙니다. http:// 또는 https://로 시작하는 URL을 입력해주세요.",
variant: "destructive"
});
return;
}
setIsSaving(true); setIsSaving(true);
try { try {
@@ -90,6 +104,9 @@ const SupabaseSettings = () => {
} }
}; };
const isHttpsUrl = supabaseUrl.startsWith("https://");
const suggestProxy = supabaseUrl.startsWith("http://") && !useProxy;
return ( return (
<div className="min-h-screen bg-neuro-background pb-24"> <div className="min-h-screen bg-neuro-background pb-24">
<div className="max-w-md mx-auto px-6"> <div className="max-w-md mx-auto px-6">
@@ -114,6 +131,21 @@ const SupabaseSettings = () => {
className="pl-10 neuro-pressed" className="pl-10 neuro-pressed"
/> />
</div> </div>
{/* URL 관련 경고 및 안내 추가 */}
{suggestProxy && (
<div className="flex items-center text-amber-500 text-xs mt-1 p-2 bg-amber-50 rounded-md">
<AlertTriangle className="h-4 w-4 mr-1 flex-shrink-0" />
<span>HTTP URL을 . CORS .</span>
</div>
)}
{isHttpsUrl && (
<div className="flex items-center text-green-500 text-xs mt-1 p-2 bg-green-50 rounded-md">
<Check className="h-4 w-4 mr-1 flex-shrink-0" />
<span>HTTPS URL을 . .</span>
</div>
)}
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@@ -248,7 +280,7 @@ const SupabaseSettings = () => {
<ul className="list-disc pl-5 text-sm text-gray-500 space-y-2"> <ul className="list-disc pl-5 text-sm text-gray-500 space-y-2">
<li> <li>
<strong>Supabase URL</strong>: Supabase URL을 . <strong>Supabase URL</strong>: Supabase URL을 .
(: http://192.168.1.100:8000) (: https://192.168.1.100:8000)
</li> </li>
<li> <li>
<strong>Anon Key</strong>: Supabase API anon/public . <strong>Anon Key</strong>: Supabase API anon/public .
@@ -256,6 +288,9 @@ const SupabaseSettings = () => {
<li> <li>
<strong>CORS </strong>: HTTP URL에 . HTTPS가 URL에 . <strong>CORS </strong>: HTTP URL에 . HTTPS가 URL에 .
</li> </li>
<li className="text-amber-500 font-medium">
HTTPS URL을 . HTTP URL을 CORS .
</li>
</ul> </ul>
</div> </div>
</div> </div>