Developing Node.js for Apigee Edge

jwhitlock

Feb 10, 2016

Apigee Edge has supported using Node.js for API proxies since 2013. For those of you hearing this for the first time, Apigee Edge allows you to write API proxies using Node.js. This approach enables you to run your Node.js-based API on Apigee Edge and have it benefit from all of the other features that Apigee Edge provides, all hosted for you.

It's pretty slick. Yet ever since this feature became available, there has been a consistently reported error: “My Node.js API proxy runs fine locally but when deployed to Apigee Edge, it fails. How do I avoid this?” Here we’ll explain the main reason this happens and how you can avoid running into this using a utility we've written.

Let’s first look at the suggested developer process for local development of Node.js APIs planned for Apigee Edge deployment.

The developer workflow

As an API author targeting Apigee Edge, your Node.js development cycle is really no different than if you were targeting any other environment. Write your code, lint check it, run your test suite, and so on. Rinse and repeat this process during your development cycle just like you would any other. But because Node.js on Apigee Edge is enabled through Trireme, there’s one more step that API authors should go through: they should run their test suites using Trireme.

While Node.js on Trireme should work, there are some parts of Trireme that don’t use native Node.js and instead use a Java-based compatibility layer. Using Trireme to run your application and/or its test suite should ensure that your Node.js API is ready for Apigee Edge.

This is actually very simple. For example, if I used Mocha to run my test suite, I might use java -jar trireme-x.y.z.jar node_modules/mocha/bin/mocha test/test-*.js to run the same test suite using Trireme instead of vanilla Node.js.

If you don't want to compile the Trireme JAR yourself or if you want to use a Node.js approach, it actually gets simpler than this. You can install the Trireme NPM module to do the same thing using trireme node_modules/mocha/bin/mocha test/test-*.js.

Regardless of how you execute your application or its test suite using Trireme, it’s an excellent way to avoid surprises when deploying your Node.js application to Apigee Edge. But it isn’t foolproof.

Trireme's pluggable HTTP adapter

While it would be nice to run your Node.js application and test suite successfully and feel confident about deploying to Apigee Edge, there’s one minor wrinkle. When running Node.js on Apigee Edge, we actually use a little known Trireme feature: Trireme's pluggable HTTP adapter.

Trireme ships with a pluggable HTTP adapter that uses the Node.js HTTP layer by default but allows for the Trireme embedder to write an HTTP adapter. Why might someone want to do this? Apigee did this for performance and security reasons. As you can imagine, running Node.js in the JVM has some overhead and, by using the custom HTTP adapter, we could do things like parsing request headers only once and various other performance and security enhancements.

Why does this matter? Well, most of the issues related to Node.js on Apigee Edge have been related to modules that use Node.js HTTP layer features that were not implemented in the Apigee Edge HTTP adapter. Why weren’t they implemented? Chances are good that the feature being used was internal or not officially public.

To give you an example, one of the first issues we ran into with Node.js on Apigee Edge was reported with this error: “TypeError: Cannot read property ‘length’ from undefined.” After some digging we realized that the Apigee Edge HTTP adapter for Trireme was not exposing the rawHeaders property for the IncomingMessage object. Why? It wasn't public in Node.js 0.10.x but later, in 0.12.x and beyond, it's been available. As with any software project, things like this are bound to happen and Node.js on Apigee Edge is no different.

To make a long story short, it's not enough to use vanilla Trireme to run your Node.js application or its test suite as a litmus test prior to deploying your Node.js API to Apigee Edge. That being said, let’s introduce you to the utility we've developed that should make this process a little more reliable.

Apigee Edge-like Node.js launcher

Introducing the Apigee Edge-like Node.js Launcher, a Trireme CLI that’s preconfigured to be very similar to Apigee Edge's Trireme. It's not an identical match, but it’s close enough, so much so that it was able to catch all reported issues caused by the pluggable HTTP adapter used in Apigee Edge.

What's better is that this launcher is actually very simple—less than 15 lines of code. The end result is that you have a JAR that’s identical to Trireme from a usage perspective but pre-configured to be just like the Edge environment your Node.js APIs run in on Apigee.

How does this change your development workflow? Not much, other than instead of using Trireme to run your Node.js application or test suite as documented above, you'd use java -jar apigee-edge-like-launcher.jar node_modules/mocha/bin/mocha test/test-*.js. That's it! It’s that simple.

Peace of mind

Neither the vanilla Trireme launcher nor the Apigee Edge-like Node.js launcher will guarantee that a successful invocation of your Node.js application or test suite means an error-free Edge deployment. But the Apigee Edge-like Node.js launcher is as close to the Edge environment as you can get for litmus testing your Node.js API prior to deploying to Apigee Edge.

As mentioned above, all of the issues tested were identifiable locally using the Apigee Edge-like Node.js launcher while the same issue ran without a problem using vanilla Trireme. Again, this is not a guarantee, but it should give you peace of mind.