Files
lunchpick/lib/data/api/naver/naver_proxy_client.dart
2025-11-19 16:36:39 +09:00

99 lines
2.8 KiB
Dart

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../../../core/network/network_client.dart';
import '../../../core/network/network_config.dart';
import '../../../core/errors/network_exceptions.dart';
/// 네이버 프록시 클라이언트
///
/// 웹 환경에서 CORS 문제를 해결하기 위한 프록시 클라이언트입니다.
class NaverProxyClient {
final NetworkClient _networkClient;
NaverProxyClient({NetworkClient? networkClient})
: _networkClient = networkClient ?? NetworkClient();
/// 웹 환경에서 프록시를 통해 HTML 가져오기
Future<String> fetchViaProxy(String url) async {
if (!kIsWeb) {
throw UnsupportedError('프록시는 웹 환경에서만 사용 가능합니다');
}
try {
final proxyUrl = NetworkConfig.getCorsProxyUrl(url);
debugPrint('Using proxy URL: $proxyUrl');
final response = await _networkClient.get<String>(
proxyUrl,
options: Options(
responseType: ResponseType.plain,
headers: {
'Accept':
'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'ko-KR,ko;q=0.9,en;q=0.8',
},
),
);
if (response.data == null || response.data!.isEmpty) {
throw ParseException(message: '프록시 응답이 비어있습니다');
}
return response.data!;
} on DioException catch (e) {
debugPrint('Proxy fetch error: ${e.message}');
debugPrint('Status code: ${e.response?.statusCode}');
debugPrint('Response: ${e.response?.data}');
if (e.response?.statusCode == 403) {
throw ServerException(
message: 'CORS 프록시 접근이 거부되었습니다. 잠시 후 다시 시도해주세요.',
statusCode: 403,
originalError: e,
);
}
throw ServerException(
message: '프록시를 통한 페이지 로드에 실패했습니다',
statusCode: e.response?.statusCode ?? 500,
originalError: e,
);
}
}
/// 프록시 상태 확인
Future<bool> checkProxyStatus() async {
if (!kIsWeb) {
return true; // 웹이 아니면 프록시 불필요
}
try {
final testUrl = 'https://map.naver.com';
final proxyUrl = NetworkConfig.getCorsProxyUrl(testUrl);
final response = await _networkClient.head(
proxyUrl,
options: Options(validateStatus: (status) => status! < 500),
);
return response.statusCode == 200;
} catch (e) {
debugPrint('Proxy status check failed: $e');
return false;
}
}
/// 프록시 URL 생성
String getProxyUrl(String originalUrl) {
if (!kIsWeb) {
return originalUrl;
}
return NetworkConfig.getCorsProxyUrl(originalUrl);
}
void dispose() {
// 필요시 리소스 정리
}
}