Azure-functions-host: Simplify Node Http Response Logic

Created on 28 Nov 2016  路  11Comments  路  Source: Azure/azure-functions-host

Currently a http response exists in two forms:

  1. context.res = bodyValue; // res is interpreted as 200 with body bodyValue
  2. context.res = { body: bodyValue, headers: ..., status: ... } // res is fully specified object

Removing option 1 is something we ought to consider, as it has some negatives:

  • We are forced to guess whether the returned object is a response based on existence of 'body' property, which in a couple cases is incorrect:

    • bodyValue has a body property (workaround is nested body inside body)

    • a response object is returned with only headers and status

  • The 'magic' code of 1 doesn't save lines of code

    • context.res = bodyValue; context.done(); vs context.res.send(bodyValue);

  • We would decrease the matrix of things we need to test (currently, different behavior in content type handling between 1 and 2)
  • Simplified documentation and examples with a single recommended way of interacting with http in node

978 #814

breaking

Most helpful comment

@stefan-akelius At present all function triggers are routed through a C# process. We use edgejs for interop between node and C#. The requests are served in C# so unfortunately we don't have access to a node generated IncomingMessage or ServerResponse (I'd love to support those types natively as well).

All 11 comments

figured this one out. 1.0 don't like raw body content. can't validate webhook that wanted text/plain response. argh.

@johnnliu for full control of the response (send raw payload, manage content type, etc), we've added a flag you can set.
Details are available here: https://github.com/Azure/azure-webjobs-sdk-script/issues/965#issuecomment-262618266

@fabiocav I tried this snippet to validate the SharePoint List web hook:
context.res = {
status: 200,
body: req.query.validationtoken,
headers: {
'Content-Type': 'text/plain'
},
isRaw: true
}
In req.query.validationtoken there is the sharepoint token for the validation that the function must to send back to SharePoint like a response in text plain, but I receive ever the message "Failed to validate the notification URL" in fact with postman if I call my function there is no response and the content type is not available
noresponse
noresponse2

No news about this issue ?

Can you share the rest of your code? I just tried myself and this works fine - I get the code back with the correct content type. Your issue is likely that your output binding for the response is using $return but in your context.done() you're not returning the response there. If you want to set the response via context.res then change your http output binding name to res.

module.exports = function (context, req) {
    context.res = {
        status: 200,
        body: req.query.validationtoken,
        headers: {
            'Content-Type': 'text/plain'
        },
        isRaw: true
    };
    context.done();
};

Only for testing I created this function:

`module.exports = function (context, req) {
context.log('Node.js HTTP trigger function processed a request. RequestUri=%s', req.originalUrl);

if (req) {
    if (req.query && req.query.validationtoken) {
        // if validationtoken is specified in query
        // immediately return token as text/plain
        context.log(req.query);
        context.log(req.query.validationtoken);

        context.res = {
                    status: 200,
                    body: req.query.validationtoken,
                    headers: {
                        'Content-Type': 'text/plain'
                    },
                    isRaw: true
                };
    }
}
context.done();

};`

I'm using postman to send a post to my azure function with in query string validationtoken=123456778 as I expect from SharePoint but doesn't work for me:
noheaders
noplaintext

As I mentioned above, I think the issue is your function.json and how your response is bound. Here's what mine looks like. Note that my output is res not $return. What does yours look like?

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

Thank you @mathewc the bindings was wrong "$return" ;-)

Maybe slightly OT but is there a specific reason you didn't just pass in the standard IncomingMessage and ServerResponse objects from node but rolled your own req and res types?

@stefan-akelius At present all function triggers are routed through a C# process. We use edgejs for interop between node and C#. The requests are served in C# so unfortunately we don't have access to a node generated IncomingMessage or ServerResponse (I'd love to support those types natively as well).

@stefan-akelius You might have a look at azure-function-express (we needs contributors)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mathewc picture mathewc  路  4Comments

ladeak picture ladeak  路  3Comments

krillehbg picture krillehbg  路  3Comments

ElvenSpellmaker picture ElvenSpellmaker  路  3Comments

paulbatum picture paulbatum  路  4Comments