| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import type { APIRoute } from "astro";
- const cache = new Map<
- string,
- { data: string; timestamp: number; headers: Record<string, string> }
- >();
- const CACHE_TTL = 5 * 60 * 1000;
- export const GET: APIRoute = async ({ request }) => {
- const url = new URL(request.url);
- const target = url.searchParams.get("url");
- if (!target) {
- return new Response(JSON.stringify({ error: "Missing url parameter" }), {
- status: 400,
- headers: {
- "Content-Type": "application/json",
- "Access-Control-Allow-Origin": "*",
- },
- });
- }
- // Validate URL
- try {
- new URL(target);
- } catch {
- return new Response(JSON.stringify({ error: "Invalid URL provided" }), {
- status: 400,
- headers: {
- "Content-Type": "application/json",
- "Access-Control-Allow-Origin": "*",
- },
- });
- }
- try {
- const cached = cache.get(target);
- const now = Date.now();
- if (cached && now - cached.timestamp < CACHE_TTL) {
- return new Response(cached.data, {
- status: 200,
- headers: {
- ...cached.headers,
- "X-Cache": "HIT",
- "Access-Control-Allow-Origin": "*",
- },
- });
- }
- const upstream = `https://feedsearch.dev/api/v1/search?url=${encodeURIComponent(
- target,
- )}`;
- const response = await fetch(upstream, {
- headers: {
- "User-Agent": "Mozilla/5.0 (compatible; MikroFeedSearch/1.0)",
- },
- });
- if (!response.ok) {
- return new Response(
- JSON.stringify({
- error: `Failed to fetch feedsearch: ${response.status} ${response.statusText}`,
- }),
- {
- status: response.status,
- headers: {
- "Content-Type": "application/json",
- "Access-Control-Allow-Origin": "*",
- },
- },
- );
- }
- const data = await response.text();
- const contentType = response.headers.get("content-type") ?? "application/json";
- const headersToCache: Record<string, string> = {
- "Content-Type": contentType,
- };
- cache.set(target, {
- data,
- timestamp: now,
- headers: headersToCache,
- });
- return new Response(data, {
- status: 200,
- headers: {
- ...headersToCache,
- "X-Cache": "MISS",
- "Access-Control-Allow-Origin": "*",
- "Cache-Control": "public, max-age=300",
- },
- });
- } catch (error) {
- return new Response(
- JSON.stringify({
- error: "Failed to fetch feedsearch",
- details: error instanceof Error ? error.message : "Unknown error",
- }),
- {
- status: 500,
- headers: {
- "Content-Type": "application/json",
- "Access-Control-Allow-Origin": "*",
- },
- },
- );
- }
- };
- export const OPTIONS: APIRoute = async () => {
- return new Response(null, {
- status: 204,
- headers: {
- "Access-Control-Allow-Origin": "*",
- "Access-Control-Allow-Methods": "GET, OPTIONS",
- "Access-Control-Allow-Headers": "Content-Type",
- },
- });
- };
|