Chapter 7 gives you a thorough look at the API Gateway. In that chapter you get to create a resource and a GET method, connect it to a Lambda function, and use Lambda proxy integration. Lambda proxy integration makes it straightforward to invoke a Lambda function via the API Gateway and to return a response. Most of the logic takes place in the function, with the Gateway proxying the request to the function and the response to the client.
The API Gateway doesn’t force you to use Lambda proxy integration, however. You can decide how to transform requests and responses within the Gateway and have more control over what goes out of the Gateway. This appendix gives you information about how to implement models and mappings and teaches you other tips and tricks not covered in chapter 7.
If you implemented the get-video-list function in chapter 7, this is an alternative way of showing how to do the same thing without proxy integration. To get started, we’ll assume that you’ve created the /videos resource and a GET method. You can begin following this appendix instead of section 7.2.3. There’s one important point to mention here, though: if you enabled Lambda proxy integration when creating the GET method, you must now turn it off. To do this, click the GET method under the /videos resource, and then click Integration Request. Make sure to unselect Use HTTP Proxy Integration if it’s selected.
We’re going to take things step by step, because there are more elements to configure in the API Gateway than if you were using proxy integration. Right now, click the GET method under /videos to see the Method Execution view.
The first step is to update the settings in your method request. Choose Method Request from the Method Execution view to access its configuration. You can do a number of things here:
Your get-video-list function doesn’t take any parameters at the moment, but let’s imagine that it can take an optional encoding. It needs to return a list of videos specific for that encoding (for example, just 720p videos if encoding is set to 720p). If encoding is not specified, then the function will return all videos just as it does now. Let’s also say that the encoding is supplied via the URL. Here’s how you’d set it up:
Integration Request is the next page you need to step through. You’ve already configured the Lambda function to invoke. All that’s left to do is configure the body mapping template. This mapping template tells the API Gateway how to transform the request, including elements such as headers and query strings, into a format the consuming service can understand. Our example has a URL query string called encoding. You might want to map it to a property called encoding on the event object that your Lambda function can access:
The API Gateway API Request and Response Payload-Mapping Template Reference (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html) is full of interesting tidbits. Not only can you extract values from the request (including those from the path, query string, or header), but you can also do quite a bit more; for example:
You also have access to the $context variable, which has a lot of useful information about the API call. You have information about the identity of the caller (if it’s provided), the HTTP method, and the gateway deployment stage from which the API call is originating.
Finally, you have access to the $util variable, which contains a few useful utility functions:
API Gateway offers a shortcut so you don’t need to specify values individually. This might be useful if you have numerous parameters and don’t want to maintain a complex mapping.
In the drop-down box next to Generate Template, select Method Request Passthrough. The API Gateway will set a template for you that maps “all parameters including path, querystring, header, stage variables, and context...” (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html; see figure E.2).
In most cases, however, you should craft your own mapping and not pass everything through to the endpoint. We did it in this example to show you the syntax, methods, and parameters that you can apply.
If you use Method Request Passthrough to get all parameters passed to the integration point, you can review what it looks like by logging the event object using CloudWatch. The following listing shows some of the properties you can access.
You’ve now configured Integration Request and Method Request. That’s enough for you to do a test, so take a breather and check if you’re on the right track.
In the Method Execution page, choose Test on the left side. You’ll be taken to a page from which you can execute a test against your GET method. If you’ve defined the encoding query string, you’ll see a text box in which you can enter a value to test it. For the moment, it does nothing, so you can leave it alone. Instead, click the Test button at the bottom of the page. You’ll see a response body on the right side (figure E.3).
It’s now time to look at the response that will be sent back to the client. As you begin using the API Gateway more and more, you might come across a scenario where the client expects data in a different format than what the API Gateway receives from its integration point. If you have complete control over the client, then it may be okay. You can modify the client and make it handle the response. But what if you don’t have control over the client? Luckily, the API Gateway has the ability to transform one schema to another. You already saw glimpses of this when you configured the Integration Request. But what you did was pretty ad hoc. To build a more-solid system, you can define a model (or a schema) and build a robust mapping template to transform data from one format to another.
If you look at the current response from the API Gateway (figure E.3), you’ll see an object with two properties (baseUrl and bucket) and an array of URLs. Each URL has five properties (Key, LastModified, Etag, Size, and StorageClass). Let’s come up with a different schema that reduces the amount of data you need to send back to the client and makes things a little more obvious. Here’s what you want to do:
First, you need to create a model in the API Gateway:
API Gateway uses JSON Schema (http://json-schema.org/) to define the expected format. If your schema conforms to JSON Schema v4 (http://json-schema.org/latest/json-schema-core.html), everything should work. You can always check if your schema is correct by running it through the online JSON Schema Validator (http://www.jsonschemavalidator.net/). For now, copy the schema from the next listing to the Model Schema editor and click Create Model.
After creating the schema, follow these steps to modify Integration Response:
One thing to be aware of: API Gateway supports JSONPath notation and Velocity Template Language (VTL), so your mapping templates can have loops and logic. See https://velocity.apache.org/engine/devel/vtl-reference.html for more information about VTL and what you can do with it, and see http://goessner.net/articles/JsonPath/ for more information about JSONPath.
Now that the mapping template has been implemented, you can retest your GET method to see if you get a different response from it. Go back to the main Method Execution window and click Test. Click the Test button and look at the response body. It should look similar to figure E.6.
So far we’ve only considered the happy path for your GET method. We’ve assumed that the GET method will always succeed and return a response with an HTTP status code of 200 and a response body with a list of your videos. But what if this isn’t always the case? What if your Lambda function throws an error or encounters an unexpected result? It would be useful to return a different HTTP status code and a different body so that your client could handle it appropriately.
Let’s see how you can handle happy and unhappy cases by extending your get-video-list Lambda function further. Remember that encoding parameter you included in the previous section? You’re now going to use it. Consider the following requirements:
You’re also going to configure the API Gateway to return the appropriate HTTP code and a response body based on what the Lambda function returns via its callback. You’ll configure Method Response and Integration Response to make it happen. This is how it will work:
You’re going to update the Lambda function to return an appropriate response when things go bad. When things go right, you’ll use your callback to return the list of files as per normal. That will generate a 200 HTTP status response code. When things go bad, however, you’ll generate and return an object with three properties: status code, message, and the encoding parameter. In the API Gateway, you’ll write a regex to match on the status code and assign the right HTTP status to the response. You’ll also extract the message and the encoding parameter and add it to the response. To do this, you’ll create a new mapping template. It will override the existing mapping template that you use for the happy case.
The regex in the API Gateway works only if you return an error via a callback. You have to use callback(result) if you want your error conditions to work. If you use callback(null, result), the API Gateway will ignore your regex and always choose the default response and template (which is 200 unless you change it).
Open index.js of the get-video-list function in your favorite text editor and replace the implementation with the following code.
Having implemented the function, deploy it to AWS by running npm run deploy from the command line.
You’re going to configure method response first. Choose Method Response in the Method Execution page and add two new responses:
Your page should look like figure E.7.
Now you can configure the integration response. In the Method Execution page, choose Integration Response. Here you need to add three responses. You’ll write a simple regex to inspect the output from the Lambda function. Then, based on the result, you’ll set the right method response status. To do this, follow these steps:
You should now see a view similar to figure E.8.
You’ve created the regex to match on the output from the Lambda function. Take .*"code":404.*, for example: the string "code":404 looks for an occurrence of that specific text in the response from the Lambda function. The characters .* allow any other text to precede and follow "code":404. If you don’t include .*, your regex will expect only "code":404 in the response.
Expand each of the new response types you’ve created and repeat the following for each response:
You now have a way to control exactly what the API Gateway returns when there’s an error. Note that you can modify response header mappings for each response code. You can access them above Body Mapping Templates.
You can test whether the new status codes work straight from the API Gateway. Click back to Method Execution and click Test. Type 2160p in the Encoding Query String text box and click Test. After the test runs, look on the right side of the page. You should see Status set to 404 and a response body based on the mapping template you set up in listing E.6.
Having configured your GET method, you need to deploy it:
You’ve now learned how to use models and mapping templates to exercise greater control over the API Gateway. Jump back to chapter 7 and carry on from section 7.2.5.
3.147.54.108