You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js如何将客户端输入URL传递到服务端执行metadata-scraper解决dns报错

解决方案

你遇到的报错是因为metadata-scraper依赖Node.js原生的dns、http等模块,只能在服务端环境运行,浏览器客户端没有这些底层API,所以需要通过Next.js的服务端API接口中转请求。

步骤1:创建服务端API接口

根据你使用的Next.js路由模式二选一即可:

App Router 实现

在app/api目录下新建scrape-metadata/route.js文件:

import { NextResponse } from 'next/server';
import getMetaData from 'metadata-scraper';

export async function POST(request) {
  try {
    const { url } = await request.json();
    // 基础合法性校验,避免恶意请求
    if (!url || !url.startsWith('http')) {
      return NextResponse.json({ error: '请输入合法的HTTP/HTTPS链接' }, { status: 400 });
    }
    const metadata = await getMetaData(url);
    return NextResponse.json(metadata, { status: 200 });
  } catch (error) {
    return NextResponse.json({ error: '元数据抓取失败' }, { status: 500 });
  }
}

Pages Router 实现

在pages/api目录下新建scrape-metadata.js文件:

import getMetaData from 'metadata-scraper';

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: '仅支持POST请求' });
  }
  try {
    const { url } = req.body;
    if (!url || !url.startsWith('http')) {
      return res.status(400).json({ error: '请输入合法的HTTP/HTTPS链接' });
    }
    const metadata = await getMetaData(url);
    return res.status(200).json(metadata);
  } catch (error) {
    return res.status(500).json({ error: '元数据抓取失败' });
  }
}

步骤2:修改客户端页面代码

把原代码中直接调用metadata-scraper的逻辑替换为调用刚才创建的API接口,同时修复原有代码的错误:

import { useState } from 'react';
import Input from '@/components/ui/Input';
import Button from '@/components/ui/Button';

// React组件名要求首字母大写,避免被识别为原生HTML标签
const Tree = () => {
  const [loading, setLoading] = useState(false);
  const [url, setUrl] = useState('');
  const [metadata, setMetadata] = useState(null);
  const [error, setError] = useState('');

  const handleFindUrl = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError('');
    setMetadata(null);
    try {
      const res = await fetch('/api/scrape-metadata', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ url }),
      });
      if (!res.ok) throw new Error('请求失败');
      const data = await res.json();
      setMetadata(data);
      console.log('抓取到的元数据:', data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };  

  return (
    <section className="bg-black mb-32 mx-auto max-w-6xl px-6 text-white">
      <form onSubmit={handleFindUrl} className="flex flex-col space-y-4">
        <Input
            type="text"
            placeholder="Link"
            value={url}
            // 修复原有onChange错误:需要从事件对象中取输入值
            onChange={(e) => setUrl(e.target.value)}
            required
            />
            <Button 
                variant="slim" 
                type="submit" 
                loading={loading}>
                抓取元数据
            </Button>
        </form>
        {/* 可选:错误提示和元数据展示 */}
        {error && <p className="text-red-500 mt-4">{error}</p>}
        {metadata && (
          <div className="mt-6 p-4 border border-gray-700 rounded">
            <h3>抓取结果:</h3>
            <p>标题:{metadata.title}</p>
            <p>描述:{metadata.description}</p>
            {metadata.image && <img src={metadata.image} alt="预览图" className="mt-2 max-w-xs" />}
          </div>
        )}
    </section>
  );
}

export default Tree;

注意事项

  • 可以在服务端接口增加请求频率限制,避免被恶意调用
  • 部分网站有反爬机制可能导致抓取失败,可根据需求在服务端增加重试、代理等兼容逻辑

内容的提问来源于stack exchange,提问作者Tom Wicks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 11:27:03