Use API Gateway with Mock integration to allow CORS from multiple Origins
Many would have faced the problem of CORS at one point in their AWS journey, when creating APIs using API Gateway. I too had been there several times. I feel that in many organisations, the power of API Gateway is very under-used, under-evaluated and under-appreciated. My learnings about this was confined even after watching several paid and free video contents offered by various learning platforms. I tried to read and comprehend AWS documentation but only after multiple discontinuous attempts over a period of few months, I am now able to understand some basics. Hence, I wanted to capture my learning of enabling CORS using Mock Integration, here.
API Gateway offers various integrations and most of us would have wondered about the use of Mock
integration other than that for testing purpose. One such use case is for resolving CORS issues.
Problem statement
When an API is requested from an origin
different from where it is hosted, due to security reasons, CORS error occurs which prevents that API call unless it is allowed using Access-Control-Allow-Origin
header. So, before a POST
call, a pre-flight is triggered which is OPTIONS
with headers like Access-Control-Allow-Headers
and Access-Control-Allow-Methods
. It also has a header called Origin
which could be like https://www.example.com
or http://localhost:3000
if you are running it from a development server.
Solution Overview
Based on our requirements, we have two cases here.
- If the
origin
is fixed or if all origins need to be allowed using wildcard like*
- If we need to allow all origins from a list.
In either case, common steps are:
Click on Create Method
and choose OPTIONS
.
Case-1:
We can directly go to Integration Response
and by defaultAccess-Control-Allow-Origin
is set to'*'
. We can change this value to 'https://www.example.com'
if in case we are accessing it from that particular origin.
Case-2:
But in this case we select Method Request
and add origin
as required
header.
Choose Mock
integration from Integration Request
(as shown in first diagram depicting various integration options). Then we need to define the logic in Mapping Templates
. This requires understanding of Velocity Template Language. Since I was in a learning phase, I was looking for some logic in VTL to help me out. Thanks to Dhiraj Agarwal, I got a solution from stackoverflow.com.
The above logic has an Array of origins under $domains
and we fetch the current origin from $input.params("origin")
. Finally if the value matches any one of the origin in Array, the Access-Control-Allow-Origin
is overridden in line 10.
Testing
I am not saying that the latency will be 3ms in real-life scenario. Since it is tested within API Gateway it is very low. All I am saying is if we integrate this with a Lambda function, some minimal additional latency will be added.
(Note: Here I am using www.example.com
without http://
after making changes in code because this testing IDE does not support additional :
. But if you test from postman
or insomnia
, it works as expected.)
In case a fallback domain is required, either we can make the logic change in Integration
using VTL or specify it in Integration Response
as shown below. When the value is not found, this one will be used.
Summary
The advantages of this solution are:
- it will have very low latency as the payload is not passed to other AWS services like lambda which can take some time to load and execute.
- Invoking lambda function will cost us for every
100ms
but this logic is handled by API gateway without any additional charges.
Stay tuned for more cost effective solutions on AWS. Special thanks to Dipti Kumari for helping me proofread.