← back to Trademarks Copyright

src/app/api/news/route.ts

35 lines

import { NextRequest, NextResponse } from "next/server";
import { parseStringPromise } from "xml2js";

/**
 * Pull Google News RSS for a given query. No API key needed.
 * Returns up to 10 most recent items.
 */
export async function GET(req: NextRequest) {
  const q = req.nextUrl.searchParams.get("q");
  if (!q) return NextResponse.json({ items: [] });

  const url = `https://news.google.com/rss/search?q=${encodeURIComponent(q)}&hl=en-US&gl=US&ceid=US:en`;
  try {
    const resp = await fetch(url, { next: { revalidate: 900 } } as RequestInit);
    if (!resp.ok) return NextResponse.json({ items: [], error: `upstream ${resp.status}` });
    const xml = await resp.text();
    const parsed = await parseStringPromise(xml, { explicitArray: false, trim: true });
    const rawItems = parsed?.rss?.channel?.item ?? [];
    const items = (Array.isArray(rawItems) ? rawItems : [rawItems]).slice(0, 10).map((it: {
      title?: string;
      link?: string;
      pubDate?: string;
      source?: string | { _?: string };
    }) => ({
      title: it.title ?? "",
      link: it.link ?? "",
      pubDate: it.pubDate ?? "",
      source: typeof it.source === "string" ? it.source : it.source?._ ?? "",
    }));
    return NextResponse.json({ items });
  } catch (e) {
    return NextResponse.json({ items: [], error: String(e) });
  }
}