Can you wildcard route paths to multiple backends in Google API Gateway? - google-cloud-platform

I'm trying to use Google API Gateway as the entry point for multiple backend services. The services have common endpoints, like /api/data that conflict with one another. I would like to pre-pend an identifier at the API Gateway level to route requests to the appropriate backend. In addition, I want to wildcard all requests versus explicitly defining every endpoint per service.
Example:
paths:
'/service_1/*':
get:
x-google-backend:
address: https://service_1/
path_translation: APPEND_PATH_TO_ADDRESS
'/service_2/*':
get:
x-google-backend:
address: https://service_2/
path_translation: APPEND_PATH_TO_ADDRESS
In the above example, I want to EXCLUDE /service_*/ from the path that is passed to the backend. Therefore a client request like /service_1/api/data would call the backend as /api/data.
Is this possible?

Related

AWS API Gateway custom domain name results in {"message":"Not Found"}

I tried to create a HTTP API through API Gateway.
This API generated a URL e.g. https://{api-id}.execute-api.{region}.amazonaws.com/
This endpoint works as intended.
After this; I created a custom domain name and under "Api Mappings", I added this newly created API, set the stage the $default and left Path (Optional) as blank. This generated another endpoint (which is supposed to be added as an A record in Route53). When I try to hit this new endpoint; I get {"message":"Not Found"}. This "connection" between the custom domain endpoint and the working api gateway endpoint doesn't seem to work. Any pointers on how to fix this?
Other Information:
I own the custom domain
Adding a custom domain required uploading a SSL certificate (I had a valid one and I uploaded it - verified and all good)
The API is a basic HTTP API which refers to a Cloudfront URL. This endpoint is fully functional and working as expected.
Endpoint Type: Regional
No multiple "Stages" for API/Routes - only a $default one

AWS API Gateway path based routing to private integrations

I am using AWS HTTP API Gateway to route requests to my integrations in the VPC.
I've added a custom domain and I want to route my requests to my integrations based on the paths in the following manner
Basically all the requests coming to the API gateway should be routed to different integrations based on the base paths but the integration should receive only the path after the base path. So all the requests coming to my.custom.domain/foo/<path1>/<path2>/<path3> should be routed to the integration Foo but the gateway should strip the base path i.e. /foo and forward the rest to the integration.
The functionality is same as below in nginx where nginx strips the foo from the request path and forwards the rest to the service
location /foo/ {
proxy_pass http://foo.service
}
I've tried adding custom domain and API mapping in the AWS API gateway but that doesn't work. My service still receives the whole path from the request and hence fails.
I am unable to find any documentation or mentions on the internet about this.
You can use routes and parameter mappings to achieve this.
Create 2 routes with 2 path mappings:
path: "/foo/{proxy+}" with parameter mapping: "/$request.path.proxy"
path: "/bar/{proxy+}" with parameter mapping: "/$request.path.proxy"
"proxy+" is a greedy path variable, so it will contain the path after /foo/ or /bar/.
You can use this variable with a parameter mapping to overwrite the path the backend will receive.
This is how it looks like in AWS CDK
const privateIntegration = new HttpServiceDiscoveryIntegration('test', service, {
parameterMapping: new ParameterMapping()
.overwritePath(MappingValue.custom('/$request.path.proxy'))
})

Can I get an example of how to connect a lambda function to a domain name?

I've been wasting about 12 hours going in circles in what seems like this:
I am trying to just make a simple static landing page in lambda and hook the root of a domain to it.
The landing page works, but api gateway didn't because AWS doesn't seem to set permissions properly by default ("internal server error" with API gateway and lambda on AWS) but now the gateway link works.
So the next steps were the following:
add a custom domain name in the api gateway
add the api mapping in the custom domain name
in route 53, create a wildcard certificate with *.domain.com and domain.com
create an A record that points to the api gateway with domain.com
create a CNAME record that points to the A record
and I get an error 403 with absolutely nothing in the log. I log both 'default' and '$default' stages in the api gateway.
I read https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-403-error-lambda-authorizer/ which is all about looking at what's in the logs...
and I find the doc is both everywhere and nowhere because it's built as chunks of 'do this' and 'do that' without ever painting a whole picture of how each piece is connected to the other, or any graph with the hierarchy of services, etc. Reminds me of code that works only when you follow the example documented and breaks otherwise.
I'm sure I'm doing something wrong, but given the lack of logs and lack of cohesive documentation, I have no idea about the problem.
Not to mention that http doesn't even connect, just https.
Can anyone outline the steps needed to achieve this? essentially: [http|https]://(www).domain.com -> one lambda function
You cannot use API Gateway for an HTTP request; it only supports HTTPS.
From the Amazon API Gateway FAQs (emphasis mine):
Q: Can I create HTTPS endpoints?
Yes, all of the APIs created with Amazon API Gateway expose HTTPS endpoints only. Amazon API Gateway does not support unencrypted (HTTP) endpoints. By default, Amazon API Gateway assigns an internal domain to the API that automatically uses the Amazon API Gateway certificate. When configuring your APIs to run under a custom domain name, you can provide your own certificate for the domain.
You can use CloudFront to automatically redirect HTTP to HTTPS. How do I set up API Gateway with my own CloudFront distribution? provides a pretty simple walkthrough of connecting an API Gateway to CloudFront (you can skip the API Gateway portion and use the one you created). The important thing you'll need to do that is not in that document is to select Redirect HTTP to HTTPS.
If you truly need HTTP traffic you're probably going to need to go with an ALB.

API Gateway: Mixing of REST APIs and HTTP APIs on the same domain name can only be accomplished through API Gateway's V2 DomainName interface error

I have created a sample API Gateway using "HTTP API".
I then add a custom domain and added the relevant CNAME record to the DNS.
I then go on Configure API mappings, to add the HTTP API but I get the following error message:
Mixing of REST APIs and HTTP APIs on the same domain name can only be accomplished through API Gateway's V2 DomainName interface. Currently, WebSocket APIs can only be attached to a domain name with other WebSocket APIs. This must also occur through API Gateway's V2 DomainName interface.
Note that adding normal "REST API" works fine.
What is the problem exactly and how do I fix it?
Note that I have since deleted all custom domains, and added this domain fresh, and it still does not work..
I got a second error message and this may explain the reason:
The error message says: "These API types may only be associated to REGIONAL domain names": this means that an HTTP API can only be associated with a REGIONAL custom domain so EDGE is not (hopefully yet) supported with EDGE custom domains.
You only have the option to use a REST API, in order to associate it with an EDGE custom domain, or to create multiple HTTP API deployments in multiple AWS Regions and use Route53 (or you own DNS provider) to map each regional deployment endpoint based on a low-latency strategy.

how to make AWS api gateway accept http instead of https

I have a Lambda function proxied by API Gateway. However, API Gateway only expose https and not http. I searched everywhere but looks like API Gateway is not possible to accept http.
So my question is how to translate http client calls to https and send to api gateway? I am asking because my client can only make http calls and they won't change.
You can put a Cloudfront distribution in front of API Gateway with to following setup:
Origin Protocol Policy: HTTPS Only
Viewer Protocol Policy: HTTP and HTTPS
Forward Headers: None
Object Caching: Use Origin Cache Headers
CloudFront is a quick solution as it's much easier to set up compared to instantiating an Elastic Beanstalk.
I have spent couple of hours trying to get this right, so just to share some good write-ups and one more gentle reminder:
This Smartcam project utilize Amazon API Gateway and CloudFront, it describes the setup procedure in details.
The official example given in Amazon's doc demonstrates how to create GET and POST method with query string parameters (e.g. /search?keyword=mars&...), JSON payload and plus path parameters. Must read!
Personal 2 cents:
if you are using query string parameters, make sure to edit behavior and then choose forward all, cache all under Query String Forwarding and Caching.
Alternatively, read this doc for another two possible configurations.
If you already set the Origin Path to your stage variable (by default: /prod), then when you invoke your CloudFront domain, skip the /prod, simply: xxxx.cloudfront.net/resource1/resource2?param1=...&param2=...
I recently had a 4 hour long phone call with an AWS representative about a similar problem we had in production stage. My situation was similar, there was nothing we could change in APIGateway to fix it (the rep tried all kinds of tricks, but nothing seemed working). So our conclusion was to spin up an EC2 instance as a proxy server for APIGateway and forward all the traffic. There was some additional work such as transferring the domain name, but overall it worked just fine. In your case, as you only need to redirect HTTP traffic, a simple ElasticBeanstalk proxy app might be enough (EB uses HTTP by default and is behind a Nginx proxy server).
You may create a CloudFront distribution just for the HTTP to HTTPS redirection.
I advise you to first obtain a SSL certificate for your domain, in ACM (Certificate Manager), the region must be us-east-1.
In CloudFront, click Create Distribution then select Web to create a web distribution.
Here are all the settings you may use, with some extra explanation. Please note that I use v0 as API Gateway stage for this example.
# ORIGIN SETTINGS
# ---
# Origin Domain Name - Paste the domain name of your API Gateway > Stages > v0 but without the path at the end
Origin Domain Name: https://<getway-id>.execute-api.eu-central-1.amazonaws.com
# Origin Path - The name of your API Gateway stage
Origin Path: /v0
# Origin ID - The ID for this origin
# By default it will be defined as `Custom-<getway-id>.execute-api.eu-central-1.amazonaws.com/v0`
# I replace `Custom` by `v0` just to quickly recognise it in the list later on.
Origin ID: v0-<getway-id>.execute-api.eu-central-1.amazonaws.com/v0
# Minimum Origin SSL Protocol - Choose the minimum SSL protocol for CloudFront to use when it establishes an HTTPS connection to your origin.
Minimum Origin SSL Protocol: TLSv1.2
# Origin Protocol Policy - HTTPS since that is all that API Gateway supports. So with HTTPS CloudFront to connects to your origin only over HTTPS.
Origin Protocol Policy: HTTPS
# DEFAULT CACHE BEHAVIOR SETTINGS
# ---
# Viewer Protocol Policy - CloudFront allowed protocol to access your web content
Viewer Protocol Policy: Redirect HTTP to HTTPS
# Allowed HTTP Methods - HTTP methods you want to allow for this cache behavior
# Select at least GET, HEAD, OPTIONS
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
# Compress Objects Automatically - No since we are not serving files via CloudFront, we are just returning redirects
Compress Objects Automatically: No
# DISTRIBUTION SETTINGS
# ---
# Price Class
# There is no extra charge for using extra locations, so you may leave it on `Use All Edge Locations`. The total request count is aggregated across all locations for the free tier.
Price Class: Use All Edge Locations
# Alternate Domain Names (CNAMEs) - The domain names of your websites
Alternate Domain Names (CNAMEs): www.example.com
# SSL Certificate - The `Custom SSL Certificate` MUST be a certificate obtained in us-east-1
# So, you may go to ACM (certificate manager) and request a certificate there
# https://console.aws.amazon.com/acm/home?region=us-east-1
SSL Certificate: Custom SSL Certificate > www.example.com
# Custom SSL Client Support - Leave to default value
Custom SSL Client Support: Clients that Support Server Name Indication (SNI)
# Security Policy - Leave to default value
Security Policy: TLSv1.2_2018
Once your CloudFront distribution deployed, go to Route 53 and select your Domain Name in your Hosted Zones.
Create a Record Set > A or select the existing A record. Then in the Record edition console:
Set Alias to Yes. Then set the Alias Target so it points to your CloudFront distribution (instead of your API Gateway if that's what you previously defined). It will appear in a dropdown, and be like www.example.com (<cloudfront-id>.cloudfront.net)
You could also use an Application Load Balancer in front of the Lambda to accomplish this:
https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html