Was this helpful?

The purpose of this document is to provide a set of standards and best practices for developing with Apigee Edge. The topics that are covered here include design, coding, policy use, monitoring, and debugging. The information has been gathered by the experience of developers working with Apigee to implement successful API programs. This is a living document and will be updated from time to time.

Development standards

Comments and Documentation

  • Provide inline comments in the ProxyEndpoint and TargetEndpoint configurations. Comments enhance readability for a Flow, especially where policy file names are not sufficiently descriptive to express the underlying functionality of the Flow.
  • Make comments useful. Avoid obvious comments.
  • Use consistent indentation, spacing, vertical alignment, etc.

Framework-style coding

  • When building and sharing API proxies and policies in a team development environment managed by source control:
    To enable DRY ("don't repeat yourself"), where possible, policy configurations and scripts should implement specialized, reusable functions. For example, a dedicated policy to extract query parameters from request messages could be called ExtractVariables.ExtractRequestParameters. A dedicated policy to inject CORS headers could be called AssignMessage.SetCORSHeaders. Those policies could then be reused for every API proxy that needs to extract parameters or set CORS headers, without requiring you to create redundant (and hence less manageable) configurations.
  • Clean up unused policies and resources (JavaScript, Java, XSLT, etc.) from API proxies, especially large resources that have the potential to slow down import and deploy procedures.

Naming Conventions

  • The Policy name attribute and the XML policy file name must be identical.
  • The Script and ServiceCallout policy name attribute and the name of the resource file should be identical.
  • DisplayName should accurately describe the policy’s function to someone who has never worked with that API proxy before..
  • Name policies according to their function, for example AssignTargetAuthHeader or AssignMessage.TargetAuthHeader, RaiseFault.InvalidUser.
  • Use proper extensions for resource files, .js for JavaScript, .py for python, and .jar for Java JAR files.
  • Variable names should be consistent. If you choose a style, such as camelCase or under_score, use it throughout the API proxy.
  • Use variable prefixes, where possible, to organize variables based on their purpose, for example, Consumer.username and Consumer.password.

API proxy development

Initial Design Considerations

  • Leverage Apigee Edge policies and functionality wherever possible to build API proxies. Avoid coding all proxy logic in JavaScript, Java, or Python resources.
  • Do not implement a ServiceCallout from one API proxy to another in the same organization, or recursively from an API proxy back to itself.
  • Do not call the Edge management API from inside API proxies. The management API is used for administrative management purposes, not API flow logic. Policies are provided for interaction with API Services entities, such as developers, apps, access tokens and so on.
  • Construct Flows in an organized manner. Multiple Flows, each with a single condition, are preferable to multiple conditional attachments to the same PreFlow and Postflow.
  • As a 'failsafe', create a default API proxy with a ProxyEndpoint BasePath of /. This can be used to redirect base API requests to a developer site, to return a custom response, or perform another action more useful than returning the default CLASSIFICATION_ERROR.
  • Use TargetServer resources to decouple TargetEndpoint configurations from concrete URLs, supporting promotion across environments.

See Load balance API traffic across multiple backend servers.

  • If you have multiple RouteRules, create one as the 'default', that is, as a RouteRule with no condition. Ensure that the default RouteRule is defined last in the list of conditional Routes. RouteRules are evaluated top-down in ProxyEndpoint.

See API proxy configuration reference

Fault Handling

  • Leverage FaultRules to handle all fault handling. (RaiseFault policies are used to stop message Flow and send processing to the FaultRules Flow.)
  • Within the FaultRules Flow, use AssignMessage policies to build the fault response, not RaiseFault policies. Conditionally execute AssignMessage policies based on the fault type that occurs.
  • Always includes a default 'catch-all' fault handler so that system-generated faults can be mapped to customer-defined fault response formats.
  • If possible, always make fault responses match any standard formats available in your company or project.
  • Use meaningful, human-readable error messages that suggest a solution to the error condition.

See Fault handling.

For industry best practices, see RESTful error response design.

Persistence

Key/Value Maps

  • Use key/value maps only for limited data sets. They are not designed to be a long-term data store.
  • Consider performance when using key/value maps as this information is stored in the Cassandra database.

See Persist data using KeyValueMap.

Response Caching

  • Do not populate the response cache if the response is not successful or if the request is not a GET. Creates, updates, and deletes should not be cached. <SkipCachePopulation>response.status.code != 200 or request.verb != “GET”</SkipCachePopulation>
  • Populate cache with a single consistent content type (for example, XML or JSON). After retrieving a responseCache entry, then convert to the needed content type with JSONtoXML or XMLToJSON. This will prevent storing double, triple, or more data.
  • Ensure that the cache key is sufficient to the caching requirement. In many cases, the request.querystring can be used as the unique identifier.
  • Do not include the API key (client_id) in the cache key, unless explicitly required. Most often, APIs secured only by a key will return the same data to all clients for a given request. It is inefficient to store the same value for a number of entries based on the API key.
  • Set appropriate cache expiration intervals to avoid dirty reads.
  • Ideally, the response cache policy should be attached to the ProxyEndpoint response PostFlow, before any format translations (XMLToJSON, JSONToXML)
  • The response cache policy to lookup the cache entry should occur in the ProxyEndpoint request PreFlow. Avoid implementing too much logic, other than cache key generation, before returning a cache entry. Otherwise, the benefits of caching are minimized.
  • In general, you should always keep the response cache lookup as close to the client request as possible. Conversely, you should keep the response cache population as close to the client response as possible.

See Reduce latency using ResponseCache.

Policy and custom code

Policy or custom code?

  • Use built-in policies first and foremost (when possible). Apigee policies are hardened, optimized, and supported. For example, use the standard AssignMessage and ExtractVariables policies instead of JavaScript (when possible) to create payloads, extract information from payloads (XPath, JSONPath), etc.
  • JavaScript is preferred over Python and Java. However, if performance is the primary requirement, Java should be used over JavaScript.

JavaScript

  • Use JavaScript if it’s more intuitive than Apigee policies (for example, when setting target.url for many different URI combinations).
  • Complex payload parsing such as iterating through a JSON object and Base64 encoding/decoding.
  • JavaScript policy has a time limit, so infinite loops are blocked.
  • Always use JavaScript Steps and put files in jsc resources folder. JavaScript Policy type pre-complies the code at deployment time.

See Programming API proxies with JavaScript .

Java

  • Use Java if performance is the highest priority, or if the logic cannot be implemented in JavaScript.
  • Include Java source files in source code tracking.

See Use Java to customize an API.

Python

  • Do not use Python unless absolutely required. Python scripts can introduce performance bottlenecks for simple executions, as it is interpreted at runtime.

Script Callouts (Java, JavaScript, Python)

  • Use a global try/catch, or equivalent.
  • Throw meaningful exceptions and catch these properly for use in fault responses.
  • Throw and catch exceptions early. Do not use the global try/catch to handle all exceptions.
  • Perform null and undefined checks, when necessary. An example of when to do this is when retrieving optional flow variables.
  • Avoid making HTTP/S requests inside of a script callout. Instead, use the Apigee ServiceCallout policy as the policy handles connections gracefully.

JavaScript

  • JavaScript on the API Platform supports XML via E4X.

See JavaScript object model.

Java

  • When accessing message payloads, try to use context.getMessage() vs. context.getResponseMessage or context.getRequestMessage. This ensures that the code can retrieve the payload, in both request and response flows.
  • Import libraries to the Apigee Edge organization or environment and do not include these in the JAR file. This reduces the bundle size and will let other JAR files access the same library repository.
  • Import JAR files using the Apigee resources API rather than including them inside the API proxy resources folder. This will reduce deployment times and allow the same JAR files to be referenced by multiple API proxies. Another benefit is class loader isolation.
  • Do not use Java for resource handling (for example, creating and managing thread pools).
  • Use @IOIntensive annotation for all Java classes. This will cause the class to run in a separate thread pool. Otherwise it runs in an I/O thread, which is in the core thread pool and has the potential to block the CPU.

See Use Java to customize an API.

Python

  • Throw meaningful exceptions and catch these properly for use in Apigee fault responses

See Customize an API using Python.

ServiceCallouts

  • Don't make ServiceCallouts to other API proxies in the same organization, including recursive callouts back into the same API proxy.
  • Build a ServiceCallout request message using the AssignMessage policy, and populate the request object in a message variable. (This includes setting the request payload, path, and method.)
  • The URL that is configured within the policy requires the scheme and host to be specified. When including a variable in a URL, configure as follows: https://apigee.com/{path}
  • Store the response object for a ServiceCallout in a separate message variable. You can then parse the message variable and keeps the original message payload intact for use by other policies.

See Call services or APIs using ServiceCallout.

Accessing entities

AccessEntity Policy

  • For better performance, look up apps by uuid instead of app name.

See Retrieve entity profiles using AccessEntity.

Logging

  • Use a common syslog policy across bundles and within the same bundle. This will keep a consistent logging format.

See Monitor flow violations using RaiseAlert.

Monitoring

Cloud customers are not required to check individual components of  Apigee Edge (Routers, Message Processors, etc.). Apigee’s Global Operations team is thoroughly monitoring all of the components, along with API health checks, given health check requests by the customer.

Apigee Analytics

Analytics can provide non-critical API monitoring as error percentages are measured.

See Use the built-in charts.

Trace

The trace tool in the API Edge management UI is useful for debugging runtime API issues, during development or production operation of an API.

See Using the Trace tool.

Security

Help or comments?

  • Something's not working: See Apigee Support
  • Something's wrong with the docs: Click Send Feedback in the lower right.
    (Incorrect? Unclear? Broken link? Typo?)