feat: fallback douban proxy

This commit is contained in:
shinya
2025-08-07 22:03:14 +08:00
parent 2f897d7f62
commit 13082212cc
5 changed files with 58 additions and 71 deletions

View File

@@ -1 +1 @@
20250807215120
20250807220314

View File

@@ -1,6 +1,7 @@
import { NextResponse } from 'next/server';
import { getCacheTime } from '@/lib/config';
import { fetchDoubanData } from '@/lib/douban';
import { DoubanItem, DoubanResult } from '@/lib/types';
interface DoubanCategoryApiResponse {
@@ -19,41 +20,6 @@ interface DoubanCategoryApiResponse {
}>;
}
async function fetchDoubanData(
url: string
): Promise<DoubanCategoryApiResponse> {
// 添加超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
// 设置请求选项,包括信号和头部
const fetchOptions = {
signal: controller.signal,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
Referer: 'https://movie.douban.com/',
Accept: 'application/json, text/plain, */*',
Origin: 'https://movie.douban.com',
},
};
try {
// 尝试直接访问豆瓣API
const response = await fetch(url, fetchOptions);
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
export const runtime = 'edge';
export async function GET(request: Request) {
@@ -99,7 +65,7 @@ export async function GET(request: Request) {
try {
// 调用豆瓣 API
const doubanData = await fetchDoubanData(target);
const doubanData = await fetchDoubanData<DoubanCategoryApiResponse>(target);
// 转换数据格式
const list: DoubanItem[] = doubanData.items.map((item) => ({

View File

@@ -1,6 +1,7 @@
import { NextResponse } from 'next/server';
import { getCacheTime } from '@/lib/config';
import { fetchDoubanData } from '@/lib/douban';
import { DoubanItem, DoubanResult } from '@/lib/types';
interface DoubanApiResponse {
@@ -12,38 +13,6 @@ interface DoubanApiResponse {
}>;
}
async function fetchDoubanData(url: string): Promise<DoubanApiResponse> {
// 添加超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
// 设置请求选项,包括信号和头部
const fetchOptions = {
signal: controller.signal,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
Referer: 'https://movie.douban.com/',
Accept: 'application/json, text/plain, */*',
},
};
try {
// 尝试直接访问豆瓣API
const response = await fetch(url, fetchOptions);
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
export const runtime = 'edge';
export async function GET(request: Request) {
@@ -92,7 +61,7 @@ export async function GET(request: Request) {
try {
// 调用豆瓣 API
const doubanData = await fetchDoubanData(target);
const doubanData = await fetchDoubanData<DoubanApiResponse>(target);
// 转换数据格式
const list: DoubanItem[] = doubanData.subjects.map((item) => ({

52
src/lib/douban.ts Normal file
View File

@@ -0,0 +1,52 @@
/**
* 通用的豆瓣数据获取函数
* @param url 请求的URL
* @returns Promise<T> 返回指定类型的数据
*/
export async function fetchDoubanData<T>(url: string): Promise<T> {
// 添加超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
// 设置请求选项,包括信号和头部
const fetchOptions = {
signal: controller.signal,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
Referer: 'https://movie.douban.com/',
Accept: 'application/json, text/plain, */*',
Origin: 'https://movie.douban.com',
},
};
try {
// 尝试直接访问豆瓣API
const response = await fetch(url, fetchOptions);
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
const fallbackUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(
url
)}`;
try {
const fallbackResponse = await fetch(fallbackUrl, fetchOptions);
if (!fallbackResponse.ok) {
throw new Error(`HTTP error! Status: ${fallbackResponse.status}`);
}
const fallbackData = await fallbackResponse.json();
if (fallbackData && fallbackData.contents) {
return JSON.parse(fallbackData.contents);
}
throw new Error('Invalid fallback response');
} catch (fallbackError) {
clearTimeout(timeoutId);
throw fallbackError;
}
}
}

View File

@@ -2,7 +2,7 @@
'use client';
const CURRENT_VERSION = '20250807215120';
const CURRENT_VERSION = '20250807220314';
// 版本检查结果枚举
export enum UpdateStatus {