I have a custom domain set up in AWS API Gateway. My intention is to use "API mappings" to send traffic for different API versions to their respective API Gateways, e.g.:
GET https://example.com/v1/foo is sent to an API gateway "APIv1" ($default stage) via an API mapping on the custom domain with path="v1".
GET https://example.com/v2/foo is sent to an API gateway "APIv2" ($default stage) via an API mapping on the custom domain with path="v2" (not shown)
The HTTP APIs themselves are configured with a single route /{proxy+} and an integration that sends requests to a private ALB:
This setup works fine as far as routing traffic goes, but the problem is that when the request makes it to the actual application, the routes the application receives are like /v1/foo instead of just /foo, which is what the app is expecting.
I've played around with different route matching and parameter mapping (of which I can find almost no examples for my use case) to no avail.
I could change my app code to match the routes that AWS is sending, but the entire point of this was to handle versioning using my AWS stack and not app code. Do I have another option?
If you create a resource called /foo and the proxy resource inside it, when you set integration you can define which path to pass and the {proxy} will have just the part after /foo, ignoring the v1 entirely.
See an example below.
In this case it is ignoring everything before v1 and it is also rewriting the integration to /api/{proxy}.
It will receive a request as GET https://example.com/abc/xyz/v1/foo and will forward to backend as GET https://example.com/api/foo.
Update
It can't be done via VPC Link, but we can use public ALB almost like private, like the explanation below.
It explain about CloudFront, but the same is valid for API Gateway.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/restrict-access-to-load-balancer.html
It's totally possible. You just need to use parameters mapping for this. Using the AWS UI it would be:
Related
I would like to specify a dynamic subdomain in an Integration Request in API Gateway, but the UI is telling me that the URL is malformed. I can add this parameter to the path of the URL with no problems (although I still get the warning "the endpoint you have entered contains parameters that are not defined in the resource path"). Is this mapping to subdomain possible using API Gateway, or do I need a lambda to accomplish this? Thanks
I couldn't get this to work, so I assume it's not supported. I ended up making a different Gateway for each subdomain (I only have a few) and using a lambda to switch between them. You could also use a lambda without a a Gateway if you have many different subdomains.
I am new to Lambda so I would like to understand how the following scenario can be deployed:
Lambda connected to API gateway ( which in turn connected to a reverse proxy)
The request from API gateway to lambda needs to be routed to 3 different ALBs each in different (VPCs) private subnets.
What configuration changes I need to bring in to achieve this apart from writing Lambda function (using python) to rewrite the urls?
It would be nice if someone can explain the message flow here.
Thanks
Abhijit
This to me seems to be multiple issues, I'll try to break down whats trying to be achieved.
Using ALBs with API Gateway
There are many options for how API Gateway can use load balancers to serve http traffic. The solution really depends on which type of API Gateway you are trying to use.
Assuming your API is either REST or WebSockets you are left with 2 choices for enabling HTTP traffic inbound to a load balancer:
Directly as a HTTP or HTTP_PROXY request, listing publicly accessible hostnames to which API Gateway will forward the traffic.
If you want to keep transit private then your only option is to create a network load balancer and make use of VPCLink to create a private connection between API Gateway and your Network resource.
If you're creating a HTTP API (sometimes referred to as API Gateway v2) then you can make use of direct connection to a private ALB, however be aware that at this time HTTP API does not support all the features of REST APIs so you would want to compare feature sets before doing this.
Using multiple load balancers to direct traffic
You determine the value per each resource/method combo, for example POST /example would be assigned its target endpoint, but only one.
My suggestion would be to make use of stage variables if you're using a REST API to specify any endpoints that you're forwarding traffic for the following reasons:
Prevents mistyping of domain names
Allows quick replacement of a hostname
Provides functionality for canary deployments to shift traffic proportionally between 2 variable names (these could be anything as long as the type is the same e.g. Lambda to another Lambda, not Lambda to a load balancer).
Using a Lambda to redirect
Technically a Lambda can perform a redirect by return a response using the below syntax
{
statusCode: 302,
headers: {
Location: 'https://api.example.com/new/path',
}
}
However be aware this will change the request to become a GET request, this will also remove the payload of the body request when the redirect occurs. Additionally you would need to set this up for every resource/method combo that you wanted to redirect.
There are 2 options that you have available to get around these issues, both involve using CloudFront combined with a Lambda#Edge function.
The first solution can act as a workaround for the request type changing, in the Origin Request event you could modify the Request URI property to match the new URI structure. By doing this your clients would be able to use the API still, whilst you would notify them of the depercations to certain paths that you were migrating.
The second solution acts as a workaround for the need to add redirects to each resource/method combo which can create a lot of mess of methods just for redirects. You could create a Lambda#Edge function to perform the same redirect on an Origin Response event. You could create mappings in your Lambda function to work out which URL it should redirect to.
There are many great examples on the Lambda#Edge example functions page
I have a website distributed with CloudFront, with S3 as an origin. I've written a Lambda function that takes a contact form submission and sends the email along with SES. The Lambda test out just fine : )
But, I'm clueless when it comes to routing POST requests from CloudFront to that backend Lambda function. How do I do this?
Update: Okay, I've got the API Gateway test triggering the Lambda function just fine, but I can't seem to call it from CloudFront (or rather using a curl command to my domain set up with CloudFront).
Do I need to list my domain as a custom domain in API Gateway?
If I list the path /api/* in my CloudFront Behaviors, do I have to mirror that in my API Gateway set up? So, does my API Gateway need to start with /api before I add specific resources?
Update 2 I think I needed to leave or remove the /dev off the end of the API Gateway URL. dev being my stage.
Update 3 Okay, it feels one step away now. I've got everything hooked up. The test request hits cloudfront, it forwards to api gateway, gateway calls lambda (at this point I'm shaking my head at how complicated we've made all this), and lambda sends back success or failure to api gateway, and we're peachy. Except, I get MethodNotAllowed when I do it from curl or the browser. Do I need to add an IAM role to CloudFront to access API Gateway?
Update 4 Still not working. And now, I'm back to getting my usual 404 error page that my Default Origin (S3). Seems like serverless is a fading dream.
Update 5 Trying a different approach, recommended here: https://serverfault.com/a/839368 The idea is to use API Gateway's Custom Domain name features with a subdomain like api.example.com and then use a Route53 Alias record to direct subdomain traffic to API Gateway. This could work. Then CloudFront would handle traffic to example.com and www.example.com, and API Gateway would get requests to api.example.com. Now the challenging bit is that in HTML forms the action attribute will have to go to a different subdomain. Let's see what kinds of errors and crazy behavior we get : (
First you would setup API Gateway in front of your Lambda function so it can be called via a POST request. It sounds like you may already have that part done?
Then if you want the POST to go through CloudFront you would add a second origin in CloudFront that points to your API Gateway.
This is all possible, but its tricky to configure. To help I created an open-source boilerplate app that correctly sets up:
A static site with CloudFront and S3
An API with API Gateway and Lambda
CORS between the static site and API
Optional OAuth 2.0 and JWT cookie for the static site
See this static JavaScript app for an example of a static site POSTing to an API backed by Lambda.
Depends on what you're using as your backend (which language, framework, etc.), there are different ways, but 'em all about one thing: Invoke
Kind-of the most generic call - HTTP is right there, the API call examples by language are referenced at the end of the doc.
I am fairly new to AWS Lambda but sure can see the benefits of it and stumbled upon the superb framework Serverless to help me built solutions on Lambda.
I started out building solutions using AWS API Gateway but really need "internal" VPC API's and not public Internet facing API's like API GW creates.
I found that Servless indeed can expose a HTTP endpoint but I can't figure out how this is done and how the URL is created.
When I deploy the Lambda from Serverless it gives me the URL, e.g.:
https://uxezd6ry8z.execute-api.eu-west-1.amazonaws.com/dev/ping
I would like to be able to find (or create) this same http listener for already existing Lambdas so my question is how is the URL created and where is teh actual HTTP listener deployed?
You might be looking for the invoke url,
1. go to https://console.aws.amazon.com/apigateway
2. select api link (which you have deployed on aws lambda).
3. select stages in left side panel and
see the invoke url.
Adding a http listener can be done by going to your lambda function, selecting the 'triggers' tab and 'add trigger', finally selecting API Gateway - but as others mentioned this does create a public facing url.
Duh, I was in the wrong AWS logon previously so the API GW was not showing any matching Serverless API and that was why I couldn't understand how they did it...
Once I logged into the AWS account that hosts the Serverless structure I can see the API GW GET API's for the Serverless HTTP listener.
I am integrating a web-relay into AWS-service which makes call-outs to a predefined path (
/some-fixed-path and it can not be configured) and I want to intercept it using a lambda on dedicated sub-domain, to keep this separated from the rest of our service, so I want the call-out to be http://subdomain.example.com/some-fixed-path.
I have a domain (lets call it example.com) registered and I have a hosted-zone defined. How can i create a record-set in the hosted-zone and use it in the API-gateway definition? (The url must not contain the stage...)
In the API-gateway definition, there is a "Custom domain name" option, but I can't figure out how to point to a record from my hosted-zone.
You should simply be able to follow the instructions for using a custom domain and then adding an alias record in your hosted zone to the CloudFront distribution provided by the API Gateway console.
You'll want to configure your custom domain with the base path pointing to your deployed stage. At that point you can than create your resource at some-fixed-path.
Note: API Gateway currently requires all APIs to be HTTPS, so if your call out can't be changed to support HTTPS, API Gateway will not work for this use case.
AWS has a detailed guide about how to do that exactly.
A few more things to pay attention to are:
Make sure you remember to re-deploy when you make any change to the API.
When you set up Base Path Mapping, make sure double check the API resource path and method. (For example, if you create the API gateway through lambda template, the API resource will be created under /{API name} instead of /).
A lot of people see Missing Authentication Token when they use API gateway for the first time due to those reasons.