Node.js Azure Functions 中流式传输 HTTP 请求和响应

本文介绍了如何在 Node.js 函数应用中流式传输HTTP请求和响应。 学习如何启用流媒体、处理大数据以及处理实时HTTP场景。

注释

HTTP 流需要 v4 编程模型。 如果你用的是v3,请看 迁移指南 来升级。

概述

借助 HTTP 流功能,可以更轻松地处理大数据、提供动态内容并支持其他核心 HTTP 方案。 它允许在 Node.js 函数应用中流式传输对 HTTP 终结点的请求和响应。 HTTP 流适用于应用需要通过 HTTP 进行客户端和服务器之间的实时交换和交互的情况。 HTTP 流还可以用于在使用 HTTP 时获取应用的最佳性能和可靠性。

先决条件

启用数据流

使用以下步骤在 Azure 和本地项目的函数应用中启用 HTTP 流:

  1. 如果计划流式传输大量数据,请修改 Azure 中的 FUNCTIONS_REQUEST_BODY_SIZE_LIMIT 设置。 默认允许的最大体大小是 104857600,这限制了你的请求大小约为 100 MB。

  2. 对于本地开发,还需要将 FUNCTIONS_REQUEST_BODY_SIZE_LIMIT 添加到 local.settings.json 文件

  3. 请将以下代码添加到您的应用中由主字段包含的任何文件内。

const { app } = require("@azure/functions");

app.setup({ enableHttpStream: true });

Tip

直接使用 request.body 以获得流媒体的最大收益。 像 request.text() 这样的方法会缓冲整个响应体并返回一个字符串,这违背了流式传输的初衷。

流示例

以下示例展示了一个通过HTTP POST请求接收数据的HTTP触发函数。 该函数将这些数据流向指定的输出文件:

const { app } = require("@azure/functions");
const fs = require("fs");
const path = require("path");

app.http("httpTriggerStreamRequest", {
  methods: ["POST"],
  handler: async (request, context) => {
    context.log("HTTP trigger function processed a request.");

    if (!request.body) {
      return {
        status: 400,
        body: "Request body is required"
      };
    }

    // Create a writable stream to a file
    const outputPath = path.join(__dirname, "streamed-output.txt");
    const writeStream = fs.createWriteStream(outputPath);

    try {
      // Stream the request body to the file
      const reader = request.body.getReader();
      let done = false;

      while (!done) {
        const { value, done: readerDone } = await reader.read();
        done = readerDone;
        
        if (value) {
          writeStream.write(value);
        }
      }

      writeStream.end();
      
      return {
        status: 200,
        body: "Data successfully streamed to file"
      };
    } catch (error) {
      context.log.error("Error streaming data:", error);
      return {
        status: 500,
        body: "Error processing stream"
      };
    }
  }
});

以下示例展示了一个 HTTP 触发函数,该函数将文件内容作为对 HTTP GET 请求的响应进行流式传输:

const { app } = require("@azure/functions");
const fs = require("fs");
const path = require("path");

app.http("httpTriggerStreamResponse", {
  methods: ["GET"],
  handler: async (request, context) => {
    context.log("HTTP trigger function processed a request.");

    const filePath = path.join(__dirname, "sample-data.txt");

    try {
      // Check if file exists
      if (!fs.existsSync(filePath)) {
        return {
          status: 404,
          body: "File not found"
        };
      }

      // Create a readable stream from the file
      const readStream = fs.createReadStream(filePath);
      
      return {
        status: 200,
        headers: {
          "Content-Type": "text/plain",
          "Transfer-Encoding": "chunked"
        },
        body: readStream
      };
    } catch (error) {
      context.log.error("Error streaming file:", error);
      return {
        status: 500,
        body: "Error streaming file"
      };
    }
  }
});

如果想用流的现成型示例应用,可以看看GitHub上的这个示例