passing cloud front custom domain URL to lambda
I have a custom domain URL (my-custom-domain.com), and the REST API supports query and path parameters.
https://my-custom-domain.com/hello
https://my-custom-domain.com?firstparam=abc&secondparam=def
The invoked lambda has to return the response with some path/query parameters appended to the custom domain URL in json body. Basically the other resources which can be accessed.
Example:
https://my-custom-domain.com/hellofromlambda1123
https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30
An Ideal usecase is pagination, where I have to give the previous and next links. How do I pass the custom domain URL to my lambda.
I am working on node js 8
In conventional JAVA programming we can achieve this by HttpServletRequest.getRequestURL().
What is the way to get the custom Domain URL. I have enabled Headers for DefaultCacheBehavior. The host in the lambda event gives the API gateway URL. Is there a way to get the mapping of the Custom Domain inside lambda?
My Cloud Formation Template for custom domain looks like this
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template
Parameters:
ServiceName:
Description: Name of the Service
Type: String
DeploymentEnv:
Default: dev
Description: The environment this stack is being deployed to.
Type: String
CertificateId:
Description: SSL Certificate Id
Type: String
DomainName:
Description: Name of the custom domain
Type: String
HostedZoneId:
Description: Id of the hosted zone
Type: String
Resources:
APIDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName:
Fn::ImportValue:
!Sub "InvokeURL-${DeploymentEnv}"
Id: !Sub 'Custom-Domain-${DeploymentEnv}'
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
Enabled: 'true'
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 0
TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
ForwardedValues:
QueryString: 'true'
Cookies:
Forward: none
Headers:
- 'Accept'
- 'api-version'
- 'Authorization'
ViewerProtocolPolicy: https-only
Aliases:
- !Sub '${DomainName}'
ViewerCertificate:
AcmCertificateArn: !Sub '${CertificateId}'
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2018
APIDNSRecord:
Type: AWS::Route53::RecordSet
DependsOn: "APIDistribution"
Properties:
HostedZoneId: !Sub '${HostedZoneId}'
Comment: DNS name for the custom distribution.
Name: !Sub '${DomainName}'
Type: A
AliasTarget:
DNSName: !GetAtt APIDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
EvaluateTargetHealth: false
Outputs:
DomainName:
Value: !GetAtt APIDistribution.DomainName
node.js aws-lambda aws-api-gateway aws-cloudfront
add a comment |
I have a custom domain URL (my-custom-domain.com), and the REST API supports query and path parameters.
https://my-custom-domain.com/hello
https://my-custom-domain.com?firstparam=abc&secondparam=def
The invoked lambda has to return the response with some path/query parameters appended to the custom domain URL in json body. Basically the other resources which can be accessed.
Example:
https://my-custom-domain.com/hellofromlambda1123
https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30
An Ideal usecase is pagination, where I have to give the previous and next links. How do I pass the custom domain URL to my lambda.
I am working on node js 8
In conventional JAVA programming we can achieve this by HttpServletRequest.getRequestURL().
What is the way to get the custom Domain URL. I have enabled Headers for DefaultCacheBehavior. The host in the lambda event gives the API gateway URL. Is there a way to get the mapping of the Custom Domain inside lambda?
My Cloud Formation Template for custom domain looks like this
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template
Parameters:
ServiceName:
Description: Name of the Service
Type: String
DeploymentEnv:
Default: dev
Description: The environment this stack is being deployed to.
Type: String
CertificateId:
Description: SSL Certificate Id
Type: String
DomainName:
Description: Name of the custom domain
Type: String
HostedZoneId:
Description: Id of the hosted zone
Type: String
Resources:
APIDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName:
Fn::ImportValue:
!Sub "InvokeURL-${DeploymentEnv}"
Id: !Sub 'Custom-Domain-${DeploymentEnv}'
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
Enabled: 'true'
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 0
TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
ForwardedValues:
QueryString: 'true'
Cookies:
Forward: none
Headers:
- 'Accept'
- 'api-version'
- 'Authorization'
ViewerProtocolPolicy: https-only
Aliases:
- !Sub '${DomainName}'
ViewerCertificate:
AcmCertificateArn: !Sub '${CertificateId}'
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2018
APIDNSRecord:
Type: AWS::Route53::RecordSet
DependsOn: "APIDistribution"
Properties:
HostedZoneId: !Sub '${HostedZoneId}'
Comment: DNS name for the custom distribution.
Name: !Sub '${DomainName}'
Type: A
AliasTarget:
DNSName: !GetAtt APIDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
EvaluateTargetHealth: false
Outputs:
DomainName:
Value: !GetAtt APIDistribution.DomainName
node.js aws-lambda aws-api-gateway aws-cloudfront
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43
add a comment |
I have a custom domain URL (my-custom-domain.com), and the REST API supports query and path parameters.
https://my-custom-domain.com/hello
https://my-custom-domain.com?firstparam=abc&secondparam=def
The invoked lambda has to return the response with some path/query parameters appended to the custom domain URL in json body. Basically the other resources which can be accessed.
Example:
https://my-custom-domain.com/hellofromlambda1123
https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30
An Ideal usecase is pagination, where I have to give the previous and next links. How do I pass the custom domain URL to my lambda.
I am working on node js 8
In conventional JAVA programming we can achieve this by HttpServletRequest.getRequestURL().
What is the way to get the custom Domain URL. I have enabled Headers for DefaultCacheBehavior. The host in the lambda event gives the API gateway URL. Is there a way to get the mapping of the Custom Domain inside lambda?
My Cloud Formation Template for custom domain looks like this
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template
Parameters:
ServiceName:
Description: Name of the Service
Type: String
DeploymentEnv:
Default: dev
Description: The environment this stack is being deployed to.
Type: String
CertificateId:
Description: SSL Certificate Id
Type: String
DomainName:
Description: Name of the custom domain
Type: String
HostedZoneId:
Description: Id of the hosted zone
Type: String
Resources:
APIDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName:
Fn::ImportValue:
!Sub "InvokeURL-${DeploymentEnv}"
Id: !Sub 'Custom-Domain-${DeploymentEnv}'
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
Enabled: 'true'
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 0
TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
ForwardedValues:
QueryString: 'true'
Cookies:
Forward: none
Headers:
- 'Accept'
- 'api-version'
- 'Authorization'
ViewerProtocolPolicy: https-only
Aliases:
- !Sub '${DomainName}'
ViewerCertificate:
AcmCertificateArn: !Sub '${CertificateId}'
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2018
APIDNSRecord:
Type: AWS::Route53::RecordSet
DependsOn: "APIDistribution"
Properties:
HostedZoneId: !Sub '${HostedZoneId}'
Comment: DNS name for the custom distribution.
Name: !Sub '${DomainName}'
Type: A
AliasTarget:
DNSName: !GetAtt APIDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
EvaluateTargetHealth: false
Outputs:
DomainName:
Value: !GetAtt APIDistribution.DomainName
node.js aws-lambda aws-api-gateway aws-cloudfront
I have a custom domain URL (my-custom-domain.com), and the REST API supports query and path parameters.
https://my-custom-domain.com/hello
https://my-custom-domain.com?firstparam=abc&secondparam=def
The invoked lambda has to return the response with some path/query parameters appended to the custom domain URL in json body. Basically the other resources which can be accessed.
Example:
https://my-custom-domain.com/hellofromlambda1123
https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30
An Ideal usecase is pagination, where I have to give the previous and next links. How do I pass the custom domain URL to my lambda.
I am working on node js 8
In conventional JAVA programming we can achieve this by HttpServletRequest.getRequestURL().
What is the way to get the custom Domain URL. I have enabled Headers for DefaultCacheBehavior. The host in the lambda event gives the API gateway URL. Is there a way to get the mapping of the Custom Domain inside lambda?
My Cloud Formation Template for custom domain looks like this
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template
Parameters:
ServiceName:
Description: Name of the Service
Type: String
DeploymentEnv:
Default: dev
Description: The environment this stack is being deployed to.
Type: String
CertificateId:
Description: SSL Certificate Id
Type: String
DomainName:
Description: Name of the custom domain
Type: String
HostedZoneId:
Description: Id of the hosted zone
Type: String
Resources:
APIDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName:
Fn::ImportValue:
!Sub "InvokeURL-${DeploymentEnv}"
Id: !Sub 'Custom-Domain-${DeploymentEnv}'
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
Enabled: 'true'
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 0
TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
ForwardedValues:
QueryString: 'true'
Cookies:
Forward: none
Headers:
- 'Accept'
- 'api-version'
- 'Authorization'
ViewerProtocolPolicy: https-only
Aliases:
- !Sub '${DomainName}'
ViewerCertificate:
AcmCertificateArn: !Sub '${CertificateId}'
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2018
APIDNSRecord:
Type: AWS::Route53::RecordSet
DependsOn: "APIDistribution"
Properties:
HostedZoneId: !Sub '${HostedZoneId}'
Comment: DNS name for the custom distribution.
Name: !Sub '${DomainName}'
Type: A
AliasTarget:
DNSName: !GetAtt APIDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
EvaluateTargetHealth: false
Outputs:
DomainName:
Value: !GetAtt APIDistribution.DomainName
node.js aws-lambda aws-api-gateway aws-cloudfront
node.js aws-lambda aws-api-gateway aws-cloudfront
edited Nov 16 '18 at 12:10
Klose
asked Nov 16 '18 at 6:58
KloseKlose
135
135
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43
add a comment |
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43
add a comment |
2 Answers
2
active
oldest
votes
Thanks to @thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host
header into an alternate request header, using a Lambda@Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host
header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host
.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com
and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host
header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
- use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
- configure your API as a custom domain (for your exposed domain)
- attaching the appropriate certificate to API Gateway, but
- do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
- use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
- whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host
header, coupled with the way CloudFront handles TLS on the back-end when the Host
header is whitelisted for forwarding.
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
add a comment |
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host
and headers.X-Forwarded-Proto
keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url andHost
is the correct domain...
– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53332884%2fpassing-cloud-front-custom-domain-url-to-lambda%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks to @thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host
header into an alternate request header, using a Lambda@Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host
header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host
.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com
and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host
header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
- use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
- configure your API as a custom domain (for your exposed domain)
- attaching the appropriate certificate to API Gateway, but
- do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
- use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
- whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host
header, coupled with the way CloudFront handles TLS on the back-end when the Host
header is whitelisted for forwarding.
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
add a comment |
Thanks to @thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host
header into an alternate request header, using a Lambda@Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host
header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host
.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com
and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host
header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
- use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
- configure your API as a custom domain (for your exposed domain)
- attaching the appropriate certificate to API Gateway, but
- do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
- use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
- whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host
header, coupled with the way CloudFront handles TLS on the back-end when the Host
header is whitelisted for forwarding.
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
add a comment |
Thanks to @thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host
header into an alternate request header, using a Lambda@Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host
header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host
.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com
and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host
header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
- use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
- configure your API as a custom domain (for your exposed domain)
- attaching the appropriate certificate to API Gateway, but
- do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
- use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
- whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host
header, coupled with the way CloudFront handles TLS on the back-end when the Host
header is whitelisted for forwarding.
Thanks to @thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host
header into an alternate request header, using a Lambda@Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host
header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host
.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com
and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host
header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
- use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
- configure your API as a custom domain (for your exposed domain)
- attaching the appropriate certificate to API Gateway, but
- do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
- use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
- whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host
header, coupled with the way CloudFront handles TLS on the back-end when the Host
header is whitelisted for forwarding.
answered Nov 16 '18 at 17:55
Michael - sqlbotMichael - sqlbot
94.6k13140206
94.6k13140206
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
add a comment |
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
Thanks I achieved it using custom origin header.
– Klose
Nov 21 '18 at 6:52
add a comment |
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host
and headers.X-Forwarded-Proto
keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url andHost
is the correct domain...
– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
|
show 2 more comments
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host
and headers.X-Forwarded-Proto
keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url andHost
is the correct domain...
– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
|
show 2 more comments
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host
and headers.X-Forwarded-Proto
keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host
and headers.X-Forwarded-Proto
keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
answered Nov 16 '18 at 9:15
thomasmichaelwallacethomasmichaelwallace
2,7551919
2,7551919
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url andHost
is the correct domain...
– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
|
show 2 more comments
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url andHost
is the correct domain...
– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Hi the "HOST" property has the API Gateway URL. But I need the Custom Domain URL. Is there a way to find the Custom Domain URL using the API Gateway URL?
– Klose
Nov 16 '18 at 9:47
Have you checked that? We use base path mapping to get a custom domain url and
Host
is the correct domain...– thomasmichaelwallace
Nov 16 '18 at 9:48
Have you checked that? We use base path mapping to get a custom domain url and
Host
is the correct domain...– thomasmichaelwallace
Nov 16 '18 at 9:48
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
Yes I have :) The "host" is the API Gateway URL. The custom Domain URL generated in the AWS CloudFront is not coming in "host" :(
– Klose
Nov 16 '18 at 9:57
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
How are you providing your domain- are you using API gateway's basePathMapping?
– thomasmichaelwallace
Nov 16 '18 at 10:11
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
I am using cloud formation template. From my API Gateway lambda I export the invoke url, and map it under cloudFront's cloud formation template under AWS::CloudFront::Distribution. Added the template in the question above.
– Klose
Nov 16 '18 at 12:07
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53332884%2fpassing-cloud-front-custom-domain-url-to-lambda%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
So the issue here seems to be that you are creating your own CloudFront distribution, and setting its Origin Domain Name to an API Gateway endpoint -- and, with this configuration, it is to be expected that API Gateway is not actually aware of the custom domain name. While this is a valid configuration and sometimes a desirable one, is there a specific reason you're doing it this way rather than configuring the custom domain name in API Gateway itself? The optimal solution may depend on your reasoning.
– Michael - sqlbot
Nov 16 '18 at 12:46
Yes @Michael-sqlbot the intention of having the cloud front aware is that, if we might want more than one routes for a given API Gateway, we would configure that in custom domain itself. Also, we would want to run all cloud formation using template files for automation.
– Klose
Nov 16 '18 at 14:43