Programming API proxies with JavaScript

You're viewing Apigee Edge documentation.
Go to the Apigee X documentation.
info

In this topic you will learn how to use JavaScript to dynamically add HTTP headers to a response message and how to parse a JSON response and return a subset of its properties to the the requesting app.

Download and try out the sample code

About this cookbook example

This cookbook example illustrates an API proxy pattern in which you implement API behavior in JavaScript. The JavaScript examples are designed to show you how to work with simple variables and message content. One sample shows you how to get and set variables. The second example shows you how to parse JSON and construct a message from the result.

Two JavaScript samples are in the API proxy:

  • setHeaders.js: This JavaScript gets the values of a few variables that are set when an API proxy is invoked. The JavaScript adds those variables to the response message so that you can see their values for each request that you make.
  • minimize.js: This JavaScript shows you how to work with message content. The idea behind this sample is that a service often returns more data than is necessary. So, the JavaScript parses the response message, extracts a few interesting properties, and then uses them to build the content of the response message.

The code for setHeader.js:

context.setVariable("response.header.X-Apigee-Target", context.getVariable("target.name"));
context.setVariable("response.header.X-Apigee-ApiProxyName", context.getVariable("apiproxy.name"));
context.setVariable("response.header.X-Apigee-ProxyName", context.getVariable("proxy.name"));
context.setVariable("response.header.X-Apigee-ProxyBasePath", context.getVariable("proxy.basepath"));
context.setVariable("response.header.X-Apigee-ProxyPathSuffix", context.getVariable("proxy.pathsuffix"));
context.setVariable("response.header.X-Apigee-ProxyUrl", context.getVariable("proxy.url"));

The code for minimize.js:

// Parse the respose from the target.
var res = JSON.parse(context.proxyResponse.content);

// Pull out only the information we want to see in the response.
var minimizedResponse = { city: res.root.city,
                          state: res.root.state };
          
// Set the response variable. 
context.proxyResponse.content = JSON.stringify(minimizedResponse);

You can access flow variables in JavaScript through the context object. This object is part of the Edge JavaScript object model. For details about the object model, see JavaScript object model.

Before you begin

Before you explore this cookbook example, you should also be familiar with these fundamental concepts:

  • What policies are and how to attach them to proxies. For a good introduction to policies, see What's a policy?.
  • The structure of a proxy flow, as explained in Configuring flows. Flows let you specify the sequence in which policies are executed by an API proxy. In this example, several policies are created and added to an API proxy flow.
  • How an API proxy project is organized on your filesystem, as explained in API proxy configuration reference.
  • A working knowledge of XML, JSON and JavaScript. In this example, you build out the API proxy and its policies with XML files that reside on the filesystem.

If you have downloaded the sample code, you can locate all of the files discussed in this topic in the javascript-cookbook sample folder. The following sections discuss the sample code in detail.

Understanding the proxy flow

To get JavaScript to execute in an API proxy, you have to attach it to a flow using a policy attachment called a 'Step'. A policy of type Javascript (note capitalization) simply contains a reference to the name of a JavaScript file. You point the policy to a JavaScript file using the ResourceURL element.

For example, the following policy references the JavaScript file called setHeader.js.

<Javascript name='setHeaders' timeLimit='200'>
    <ResourceURL>setHeaders.js</ResourceURL>
</Javascript>

You can attach this policy to an API proxy flow as you would any other policy type. By attaching the policy to the API proxy flow, you indicate where the JavaScript should be executed. This enables you to execute JavaScript that interacts with request messages or response message as those messages 'flow' through the API proxy. In this example, both JavaScripts execute in the response flow, since the policies do two things: set HTTP headers on the response message and 'minimize' the response message that Apigee Edge returns to the requesting app.

If you open this flow configuration in the management UI, you will see the flow configuration below.

Select Proxy Endpoints > default > PostFlow in the Navigator pane.

The corresponding XML configuration for the ProxyEndpoint named 'default' is shown below.

<ProxyEndpoint name="default">
  <PostFlow>
    <Response>
      <!-- Steps reference policies under /apiproxy/policies -->
      <!-- First, set a few HTTP headers with variables for this transaction. -->
      <Step><Name>setHeaders</Name></Step>
      <!-- Next, transform the response from XML to JSON for easier parsing with JavaScript -->
      <Step><Name>transform</Name></Step>
      <!-- Finally, use JavaScript to create minimized response with just city and state. -->
      <Step><Name>minimize</Name></Step>
    </Response>
  </PostFlow>
  <HTTPProxyConnection>
        <!-- BasePath defines the network address for this API proxy. See the script 'invoke.sh' to see how the complete URL for this API proxy is constructed.-->
    <BasePath>/javascript-cookbook</BasePath>
     <!-- Set VirtualHost to 'secure' to have this API proxy listen on HTTPS. -->
    <VirtualHost>default</VirtualHost>
  </HTTPProxyConnection>
  <RouteRule name="default">
    <TargetEndpoint>default</TargetEndpoint>
  </RouteRule>
</ProxyEndpoint>

Here's a summary of the flow's elements.

  • <Request> - The <Request> element consists of several <Step> elements. Each step calls one of the policies that you create through the rest of this topic. These policies attach a JavaScript to the API proxy flow, and the location of the policy attachment determines when the JavaScript executes.
  • <Response> - The <Response> element also includes <Steps>. These steps also call policies that are responsible for processing the final response from the target (which in this example is Apigee's mock service target--note the HTTPTargetConnection setting in under /apiproxy/targets/default.xml.)
  • <HTTPProxyConnection> - Specifies the host and URI path that define the network address that apps call to consume this API.
  • <RouteRule> - This element specifies which TargetEndpoint configuration is invoked by the ProxyEndpoint.

Adding JavaScript code to a proxy

JavaScript (like Python scripts, Java JAR files, XSLT files, and so on) are stored as resources. When you are just starting to work with JavaScript it is easiest to store your JavaScript files in the API proxy. As you advance, JavaScript should be made as generic and reusable as possible, and then stored at the environment or organization level. This prevents you from having to store the same JavaScript files in multiple API proxies, which can quickly become unmanageable.

To learn about storing resources at the organization and environment level, see Resource files.

Try it out

For instructions on deploying and calling the proxy, see the JavaScript cookbook README.

Importing and deploying the API proxy

After you make changes, you can Save the API proxy in the API proxy builder tool in management UI.

Or you can run the following command in the directory /api-platform-samples/doc-samples/javascript-cookbook.

$ sh deploy.sh

Testing JavaScript

Run the following command in the directory /api-platform-samples/doc-samples/javascript-cookbook.

$ sh invoke.sh

The curl flag -v is used in the shell script to view HTTP headers on the response message modified by the JavaScript.

You can directly submit a request as follows:

$ curl -v http://{org_name}-test.apigee.net/javascript-cookbook 

If the JavaScript executes properly, you will see a response like the following:

< X-Apigee-Demo-Target: default
< X-Apigee-Demo-ApiProxyName: simple-javascript
< X-Apigee-Demo-ProxyName: default
< X-Apigee-Demo-ProxyBasePath: /javascript-cookbook
< X-Apigee-Demo-ProxyPathSuffix: /xml
< X-Apigee-Demo-ProxyUrl: http://rrt331ea.us-ea.4.apigee.com/javascript-cookbook/xml
 
{"city":"San Jose","state":"CA"}

You can now modify the JavaScript to try new things, redeploy the API proxy, and verify the results by submitting the same request. Always make sure you deploy the API proxy that contains your JavaScript to have your changes take effect.

Script errors

You will inevitably see errors when writing JavaScript. The format of JavaScript errors that you will see issued by an API proxy is shown below.

{  
   "fault":{  
      "faultstring":"Execution of rewriteTargetUrl failed with error: Javascript runtime error: \"TypeError: Cannot find function getVariable in object TARGET_REQ_FLOW. (rewriteTargetUrl_js#1). at line 1 \"",
      "detail":{  
         "errorcode":"steps.javascript.ScriptExecutionFailed"
      }
   }
}

When to use JavaScript

On Apigee Edge, there is usually more than one way to implement specific functionality. Use out-of-the-box policies where possible, and avoid the temptation to code all of your API proxy logic in JavaScript. Even though Apigee Edge leverages compiled JavaScript to improve performance, it is unlikely that JavaScript will perform as well as Policies. JavaScript may be more difficult to maintain and debug. Reserve JavaScript for functionality that is unique to your requirements.

If performance is a concern for custom functionality, use Java where possible.

Summary

In this cookbook topic, you learned how JavaScript can be included in an API proxy configuration to implement custom behavior. The custom behavior implemented by the samples demonstrate how to get and variables, and how to parse JSON and construct custom response messages.