Giter Site home page Giter Site logo

azure-function-express's Introduction

azure-function-express

Function logo

Allows Express usage with Azure Function

npm version Node Node Node Travis Status Coverage Status MIT licensed

Description

Connect your Express application to an Azure Function handler, and make seamless usage of all middlewares you are already familiar with.

Usage

In your index.js:

const createHandler = require("azure-function-express").createHandler;
const express = require("express");

// Create express app as usual
const app = express();
app.get("/api/:foo/:bar", (req, res) => {
  res.json({
    foo  : req.params.foo,
    bar  : req.params.bar
  });
});

// Binds the express app to an Azure Function handler
module.exports = createHandler(app);

Make sure you are binding req and res in your function.json:

{
  "bindings": [{
    "authLevel" : "anonymous",
    "type"      : "httpTrigger",
    "direction" : "in",
    "name"      : "req",
    "route"     : "foo/{bar}/{id}"
  }, {
    "type"      : "http",
    "direction" : "out",
    "name"      : "res"
  }]
}

To allow Express handles all HTTP routes itself you may set a glob star route in a single root function.json:

{
  "bindings": [{
    "authLevel" : "anonymous",
    "type"      : "httpTrigger",
    "direction" : "in",
    "name"      : "req",
    "route"     : "{*segments}"
  }, {
    "type"      : "http",
    "direction" : "out",
    "name"      : "res"
  }]
}

Note that segments is not used and could be anything. See Azure Function documentation.

All examples here.

Context

All native Azure Functions context properties, except done, are exposed through req.context.

As en example, you can log using:

app.get("/api/hello-world", (req, res) => {
  req.context.log({ hello: "world" });
  ...
});

Runtime compatibility

Supported Node version are:

Azure Functions runtime v1 and v2 beta are both supported.

License

Apache 2.0 © Yves Merlicco

azure-function-express's People

Contributors

cloudify avatar cyrusnajmabadi avatar maktwin avatar nevercast avatar yvele avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-function-express's Issues

res object seems to be missing setHeader()

This looks like an excellent solution for a low bandwidth web serving using functions - eg static pages for a SPA.

however I'm getting an error using your example in the finalhandler module used by express. It appears your mock response object is missing setHeader()

express: 2.5.11
finalhandler: 0.5.0

https://github.com/pillarjs/finalhandler/blob/master/index.js#L202

Perhaps the issues is your code is written for a specific version of express and they're been breaking changes since?

2.0 seems to have broken static file serving on azure.

I have the following code in my function-app:

app.use("/", express.static("www"));

This results in the following runtime exception:

2018-09-07T22:14:29.829 [Info] Function started (Id=65d1f81f-f1ed-4d9f-844e-7fdcae8cf5c6)
2018-09-07T22:14:31.782 [Error] A ScriptHost error has occurred
2018-09-07T22:14:31.782 [Error] System.InvalidOperationException : TypeError: Cannot read property 'length' of null
    at ServerResponse.OutgoingMessage._send (_http_outgoing.js:137:38)
    at ServerResponse.OutgoingMessage.write (_http_outgoing.js:491:16)
    at ReadStream.ondata (_stream_readable.js:555:20)
    at emitOne (events.js:96:13)
    at ReadStream.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at ReadStream.Readable.push (_stream_readable.js:134:10)
    at onread (fs.js:2018:12)
    at FSReqWrap.wrapper [as oncomplete] (fs.js:682:17)

Note the calls into the new methods inherited by OutgoingMessage.

I'm not sure what's up here but i think this starting breaking when the change to derive from NativeOutgoingMessage. Do you know what's up @yvele ? Do you have a recommendation on what can be used instead?

Package hardcoded to only work on Node <7

Hi Yves. We'd like to use this great package. However, we're running into a problem due to it having a hard blocker on the version of hte node engine being <7. Our system works by allowing one to compile with a local version of node (that can effectively be pretty much any version), which then will finally run on Azure (which also supports 8.11.1 and 10.6.0).

This blocker prevents us from supporting that. Is there a reason this needs to be in here? From looking at your code, i can't see anything in it that is particularly node version specific.

Would you be willing to remove this upper-bound blocker? I'd be happy to submit the PR for it if so.

I can not get the examples to work with v1 and v2

Hello,
I can not get the example "all-routes" to work. I tried Azure Functions Core Tools v1 and v2.

My steps:

  • Installing v1 or v2
  • Download the example
  • Run CMD as admin and switch to the folder "all-routes"
  • Running the command "func host start"

I request the following url: http://localhost:7071/api/exptest

My node version: 8.9.4

In v2, I can see that there are requests incoming but they are answered just with 404.
In v1, the application does not want to even start correctly. After the message "Job host started", there is an endless loop of the yellow message "The host is taking longer than expected to start.".

What I am doing wrong?

Suggestion: Create a channel in Slack or Gitter where everyone can subscribe and ask questions or answer them.

Best regards and thank you

Not working with Azure Functions V2 beta

I have been trying to make this work for a couple of days and I failed.
I saw older closed issues and unfortunately nothing worked.

The way I use it as follows:
1- Create azure locally via (func init, func new)
2- Initialize npm via (npm init)
3- install express and azure-function-express packages
4 - copy paste the basic example (index.js and function.json)
5- start the function via (func start)

Http body already parsed

Thank you for your great product!!
I love it. :)

I found a compatibility issue between pure-express and azure-function-express.

In pure-express, the request body is not parsed. It is raw data.
In azure-function-express, the request body is already parsed. It is object.

My workaround is as below:

app.post('path', 
  (req, res, next) => { req.body = req.rawBody; next(); },
  otherMiddlewares,
  (req, res) => {
    // do something
  });

I couldn't use bodyParser module on azure-function-express.

Broken in GA Functions 2.0 runtime

Thanks for updating to the 2.0 beta run time.

I just tried it with the GA runtime version and it doesn't work when running in a FunctionApp on Azure, but works fine in the local emulator. The example code in an empty app just crashes HTTP 500 straight up.

I enabled log streaming, diagnostic logging against blob storage and app insights detailed tracing, but all just print a generic error code as output and don't provide provide anything further. Sorry I can't be of more help. Let me know if I can be.

Changelog

Why doesn't this library have any changelogs? This seems really unprofessional and lazy.

Content-Type doesn't work correctly

I'm trying to make POST request and send JSON data to Azure Function using application/json Content-Type. But the function call hangs and return timeout instead of result.

App has the following configuration

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

Locally such expressjs application works perfectly. But looks like some trouble with Content-Type on Azure.

However when I change configuration to this one

app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(bodyParser.urlencoded({ extended: true }));

My POST requests pass. But for x-www-form-urlencoded it still can't parse the data and returns timeout.

Could you please help me to understand why it doesn't work? Thank you

writeHead doesn't work as expected when passing headers as second parameter

Hey,

first of all: thanks for providing this library!

I ran into an issue with another library where writeHead is called like this:

res.writeHead(302, {
   'Access-Control-Allow-Origin': '*',
   'Location': path
});

It took me some time to realize, that azure-function-express provides its own implementation of this method. It seems that there is a incompatibility, as the original one allows for the second statusMessage to be omitted as you can see in the Node documentation:

const body = 'hello world';
response.writeHead(200, {
  'Content-Length': Buffer.byteLength(body),
  'Content-Type': 'text/plain' });

https://nodejs.org/api/http.html#http_response_writehead_statuscode_statusmessage_headers

The implementation provided by azure-function-express doesn't support this call signature:

function writeHead(context, statusCode, statusMessage, headers) {
  // 1. Status code
  statusCode |= 0; // eslint-disable-line no-param-reassign
  if (statusCode < 100 || statusCode > 999) {
    throw new RangeError(`Invalid status code: ${statusCode}`);
  }

  // 2. Status message
 this.statusMessage = statusMessage || statusCodes[statusCode] || "unknown";

  // 3. Headers
  if (this._headers) {
    // Slow-case: when progressive API and header fields are passed.
    if (headers) {
      const keys = Object.keys(headers);
      for (let i = 0; i < keys.length; i++) {
        const k = keys[i];
        if (k) {
          this.setHeader(k, headers[k]);
        }
      }
    }
    // only progressive api is used
    headers = this._renderHeaders(); // eslint-disable-line no-param-reassign
  }

  // 4. Sets everything
  context.res.status = statusCode;
  context.res.headers = headers;
}

https://github.com/yvele/azure-function-express/blob/master/src/OutgoingMessage.js#L44

Misleading Readme regarding context

Commit dfa7aff added the entire context to the request object, stubbing log, and removing done.

The README file still indicates that only log is exposed. This may lead to issues requesting that everything (such as bindings) be exposed, which is what I was about to do before this one.

I'm happy to make the pull request if you just want to update the readme to state that the only thing missing from context is the done function. Otherwise, I'll leave this up for discussion.

error, warn, info, and verbose log functions are not bind to the sanitized context

Observed that the error, warn, info and verbose are removed from the context when the context object is sanitized to remove the "done" function.

The _extends() function in the IncomingMessage file is removing these functions. Only the "log" function is available in the context object.

It would be nice if we could use these log level functions.

Context object before sanitized;
image

Context object after sanitized:
image

Not getting it to work

Hey, I've been trying to get this to work without success.
My index.js:

const createHandler = require("azure-function-express").createHandler;
const express = require("express");
...long lists of require...
const app = express();
app.use(function(req, res, next){
   var data = "";
   req.on('data', function(chunk){ data += chunk})
   req.on('end', function(){
       req.rawBody = data;
       req.body = JSON.parse(data);
       next();
   })
})

app.post("/api/parser",
  ... lists of middlewares...
  (req, res) => {
		res.sendStatus(200)
	}
);
module.exports = createHandler(app);

my function.json:

{
  "bindings": [
    {
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "authLevel": "function",
      "methods": [ "post" ],
      "route": "parser"
    },
    {
      "type": "http",
      "name": "res",
      "direction": "out"
    }
  ],
  "disabled": false
}

basically a post request to the endpoint starts but never ends... it does not even log the first middleware

URL format

Is it possible to unpack the relationship between the route definition for the function and express mapping?

Where does segments come from?

Can you provide an example URL for invoking you sample route in the README

thanks for this great code

sendFile fails with TypeError: Cannot read property 'length' of null

I am trying to use azure-function-express in my code.

Here is my piece of code in index.js:

const createHandler = require("azure-function-express").createHandler;
const express = require("express");
var myRouter = require('./routes/myrouter.js');
const app = express();
app.use("/api/files", myRouter);
 
module.exports = createHandler(app);

Here is my myrouter.js:

var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {
  console.log('Sending file');
  var options = {
    root: __dirname + '/public/'
  };

  var fileName = 'package.zip';
  res.sendFile(fileName, options, function (err) {
    if (err) {
      console.log(err);
      next(err);
    } else {
      console.log('Sent:', fileName);
    }
  });
})

module.exports = router

When I call this API, it fails at the res.sendFile(fileName,....) step with the following error.
Note: It doesn't even reach the if(err) step.

Sending file
Worker ce5e00ff-a507-4910-92cc-8ce08323c082 uncaught exception:  TypeError: Cannot read property 'length' of null
Worker ce5e00ff-a507-4910-92cc-8ce08323c082 exited with code 1
    at ServerResponse._send (_http_outgoing.js:232:33)
    at write_ (_http_outgoing.js:667:15)
    at ServerResponse.write (_http_outgoing.js:617:10)
    at ReadStream.ondata (_stream_readable.js:639:20)
    at emitOne (events.js:116:13)
    at ReadStream.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at ReadStream.Readable.push (_stream_readable.js:208:10)
    at fs.read (fs.js:2051:12)
Debugger attached.
Waiting for the debugger to disconnect...
Language Worker Process exited.
node exited with code 1
 Worker ce5e00ff-a507-4910-92cc-8ce08323c082 uncaught exception:  TypeError: Cannot read property 'length' of null.

The problem goes away, if I change the index.js to just use express.js (without any other changes)
Updated index.js which is working:

const createHandler = require("azure-function-express").createHandler;
const express = require("express");
var myRouter = require('./routes/myrouter.js');
const app = express();
app.use("/api/files", myRouter);

app.listen(3030, ()=> console.log("Listening on port: ", 3030));

Can you please look into the issue

Node engine version

Hi,
Is there any reason this package is set to ">=6.11.2 <11"? Node LTS is now 12.14.0. Happy to do a PR if no issues?
Thanks

Support for multi-part file uploads

Have you tested multi-part file uploads with this adapter? All attempts I've tried thus far cause the web request via postman to not respond and usually timeout after 5 minutes. I also usually see this log in the function portal editor:

2017-06-21T05:04:30.644 Microsoft.Azure.WebJobs.Host: Timeout value of 00:05:00 was exceeded by function: Functions.FileUpload.

I've tried using the multer middleware with both it's memory storage as well as multer-azure to attempt to store uploads into azure blob storage.
I've also tried using busboy directly with req.pipe(busboy) to no avail.

It's likely there is a problem with my code (and I can give some examples of what I'm trying per the above) but wanted to verify if it should work before I spend too much more time on it.

Thanks.

AzFunc 'context' object

Hi Yves

I haven't find any sample that show a usage of the Azure Functions "context" object.
This one is passed through the function as arg when you create a new HTTP Trigger Function : module.exports = function (context, req) and allow you to .log() information, very useful.

Could you tell me how could I get this object within the context of using your library please ?
Many thanks :)

Kind Regards

Olivier

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.