如何通过管道传输到 Next.js 13 api 响应?

may*_*513 8 javascript typescript fetch-api next.js next.js13

早些时候,我能够将另一个 api 调用的响应通过管道传输到 Next.js api 响应,如下所示

export default async function (req, res) {
    // prevent same site/ obfuscate original API
    // some logic here 
    fetch(req.body.url).then(r => {
      r.body.pipe(res);
    }).catch(err => {
      console.log(err);
      res.status(500).send("Invalid Url");
    })
}
Run Code Online (Sandbox Code Playgroud)

效果很好。但现在response.bodyfrom fetch API 没有pipe方法了。相反,它有pipeTo方法pipeThrough。并且 Next.jsres:NextApiResponse不可分配给WritableStream.

我还尝试创建blob( await r.blob()) 并使用res.send(blob)res.send(blob.strem())。一开始似乎可以工作,但前端接收到的数据不正确(基本上fetch().then((res) => res.blob()).then((blob) => URL.createObjectURL(blob)))会给出损坏的结果)。

may*_*513 0

这是一个非常有效的技巧!

const https = require("https");

export default async function handler(req, res) {
   try {
      const url = `your-url`;
      res.status(200);
      https.get(url, (response) => {
        response.pipe(res);
        response.on("finish", res.end);
      });
    } catch (err) {
      console.log(err);
      res.status(500).send("Invalid Url");
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

上述技巧对于一些简单的情况非常有效,但在存在重定向时会失败。

正如 Klesum 建议的那样,Readable API 的效果比这更好

import { Readable } from 'node:stream';

export default async function (req, res) {
    fetch(req.body.url).then(r => {
      Readable.fromWeb(r.body).pipe(res);
    })
}
Run Code Online (Sandbox Code Playgroud)

TypeScript 对此有所抱怨,但您可以忽略该行的 ts 警告// @ts-ignore,它会正常工作。