Skip to content

$return http binding returns body buffers as JSON #252

Closed
@dhensby

Description

@dhensby

I am trying to serve an image from a function app running on node. At the moment we are doing this successfully using the context.res binding, however we are migrating our function apps to use the $return output name/binding (as is the recommendation in the docs for functions with a single output).

However, there seems to be inconsistent behaviour with named output bindings and the $return output binding. It appears that the isRaw flag is being ignored or not acted on in the same way when using the $return binding compared to a named binding.

Investigative information

Please provide the following:

  • Timestamp: 10/21/2019, 2:57:25.913 PM
  • Function App version (1.0 or 2.0): 2.0
  • Function App name: -
  • Function name(s) (as appropriate): -
  • Invocation ID: f40d7cbb-c5d1-435f-ae4c-058d4f9fe647
  • Region: West Europe

Repro steps

Create a function like so:

function.json:

{
  "disabled": false,
  "tracing": {
    "consoleLevel": "verbose"
  },
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "route": "image",
      "methods": ["GET"],
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

index.js:

module.exports = async () => {
    return {
        status: 200,
        headers: { 'content-type': 'image/jpeg' },
        body: Buffer.from([255, 216, 255, ...]), // this is the opening byte sequence for a jpg
        isRaw: true,
    };
}

Expected behavior

The response should be sent to the browser without being mangled (the isRaw flag is set to true) and the Buffer should be output as binary

$ curl [function host]/image
Date: Mon, 21 Oct 2019 15:22:45 GMT
Content-Type: image/jpeg
Content-Length: 38

���

Actual behavior

The response is a json-encoded Buffer and sent to the browser (with ; charset=utf-8 appended to the content type)

$ curl [function host]/image
Date: Mon, 21 Oct 2019 15:22:45 GMT
Content-Type: image/jpeg; charset=utf-8
Content-Length: 38

{"type":"Buffer","data":[255,216,255]}

Known workarounds

Use a named output binding:

function.json:

{
  "disabled": false,
  "tracing": {
    "consoleLevel": "verbose"
  },
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "route": "image",
      "methods": ["GET"],
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

index.js:

module.exports = async (context) => {
    context.res = {
        status: 200,
        headers: { 'content-type': 'image/jpeg' },
        body: Buffer.from([255, 216, 255, ...]), // this is the opening byte sequence for a jpg
        isRaw: true,
    };
}

Related information

This is a duplicate of Azure/azure-functions-host#3892 but hopefully provides some greater detail

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions