Azure Functions: Support for HTTP Streams in Node.js is now in Preview

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Community Hub.

Azure Functions support for HTTP streams in Node.js is now in preview. With this feature, customers can now stream HTTP requests to and responses from their Functions Apps. 

 

Being one of the most requested features for Azure Functions, we’re confident that this release will unblock Node.js Functions customers and make scenarios like processing large data, streaming OpenAI responses, delivering dynamic content etc. possible. Customers can leverage this feature for use cases where real time exchange and interaction between client and server over HTTP connections is needed. We recommend using streams to get the best performance and reliability for your app. 

 

HTTP Streams in Node.js is supported only in the Azure Functions Node.js v4 programming model. Follow these instructions to try out HTTP Streams for your Node.js apps.

 

Prerequisites

 

  • Version 4 of the Node.js programming model. Learn more about the differences between v3 and v4 in the migration guide.
  • Version 4.3.0 or higher of the @azure/functions npm package.
  • If running in Azure, version 4.28 of the Azure Functions runtime.
  • If running locally, version 4.0.5530 of Azure Functions Core Tools.

 

Steps

 

  1. If you plan to stream large amounts of data, adjust the app setting FUNCTIONS_REQUEST_BODY_SIZE_LIMIT in Azure or in your local.settings.json file. The default value is 104857600, i.e., limiting your request to 100mb maximum.

  2. Add the following code to your app in any file included by your main field.

    JavaScript

    const { app } = require('@azure/functions'); app.setup({ enableHttpStream: true });


    TypeScript

    import { app } from '@azure/functions'; app.setup({ enableHttpStream: true });

     

  3. That's it! The existing HttpRequest and HttpResponse types in programming model v4 already support many ways of handling the body, including as a stream. Use request.body to truly benefit from streams, but rest assured you can continue to use methods like request.text() which will always return the body as a string.

 

Example code

 

Below is an example of an HTTP triggered function that receives data via an HTTP POST request, and the function streams this data to a specified output file:
 
JavaScript
const { app } = require('@azure/functions'); const { createWriteStream } = require('fs'); const { Writable } = require('stream'); app.http('httpTriggerStreamRequest', { methods: ['POST'], authLevel: 'anonymous', handler: async (request, context) => { const writeStream = createWriteStream('<output file path>'); await request.body.pipeTo(Writable.toWeb(writeStream)); return { body: 'Done!' }; }, });

TypeScript
import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions'; import { createWriteStream } from 'fs'; import { Writable } from 'stream'; export async function httpTriggerStreamRequest( request: HttpRequest, context: InvocationContext ): Promise<HttpResponseInit> { const writeStream = createWriteStream('<output file path>'); await request.body.pipeTo(Writable.toWeb(writeStream)); return { body: 'Done!' }; } app.http('httpTriggerStreamRequest', { methods: ['POST'], authLevel: 'anonymous', handler: httpTriggerStreamRequest, });

 

Below is an example of an HTTP triggered function that streams a file's content as the response to incoming HTTP GET requests:

 

JavaScript

const { app } = require('@azure/functions'); const { createReadStream } = require('fs'); app.http('httpTriggerStreamResponse', { methods: ['GET'], authLevel: 'anonymous', handler: async (request, context) => { const body = createReadStream('<input file path>'); return { body }; }, });

 

TypeScript

import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions'; import { createReadStream } from 'fs'; export async function httpTriggerStreamResponse( request: HttpRequest, context: InvocationContext ): Promise<HttpResponseInit> { const body = createReadStream('<input file path>'); return { body }; } app.http('httpTriggerStreamResponse', { methods: ['GET'], authLevel: 'anonymous', handler: httpTriggerStreamResponse, });

 

Sample code

 

For a ready-to-run app with more detailed code, check out this GitHub repo.

 

Known issues

 

The request.params object will be an empty object. The suggested workaround is to use a package like path-to-regexp to parse the request.url property. Keep in mind that Azure Functions only supports ASP.NET Core route templates (i.e. user/{name}) when registering your function, so you will likely need to use a different syntax (i.e. /user/:name) when parsing the url.

 

Here is example code using the suggested workaround:

import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions'; import { match } from 'path-to-regexp'; export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { const parseRoute = match('/api/user/:name'); const route = parseRoute(new URL(request.url).pathname); const params = route ? (route.params as Record<string, string>) : {}; const name = params.name || 'world'; return { body: `Hello, ${name}!` }; } app.http('httpTrigger1', { methods: ['GET', 'POST'], route: 'user/{name}', authLevel: 'anonymous', handler: httpTrigger1, });
 
Do try out this feature and share your valuable feedback with us on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.