APIGateway mapping header to path via proxy - amazon-web-services

I am trying to proxy a request though API gateway to an internal service.
My external request looks like:
Path: /resources
Headers: owner_id passed along which was decoded via an authorizer in a previous step.
The proxied endpoint I would like to hit is:
/owner/{owner_id}/resources
Is it possible to pull a header out and use this as a path parameter to the internal API?

Set an Endpoint URL like http://httpbin.org/anything/{owner_id}/blah1/blah2 in Integration Request
in the same Integration Request, add a Mapping Templates : "When there are not templates defined (recommended)) section, add a Content-Type : application/json with a template body of #set($context.requestOverride.path.owner_id = $input.params("owner_id"))
See also: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

Related

AWS API Gateway Not Passing Custom Headers

I have an API Gateway request where I am passing a custom header that is not being passed into the Lambda which is its target. First and foremost, I checked the verbose logs for the API Gateway Instance and can see the custom header called x-treasury-system being passed in and present in Method request headers:
But it is not present in Endpoint request headers:
Which is why I think its not ending up in the Lambda. I have the following header mappings setup - In the Method Request:
And in the Integration Request:
What am I missing? It seems that all is in order to pass that header, I double checked in lambda logs when printing out the headers that it is for sure not coming in.

AWS API Gateway expects the request URL to be encoded twice

My API is a request that can potentially have spaces in the pathParameters.
/data/{id}/hello/{Some message with a space}.
A sample request would be /data/23/hello/Say%20Hi
My angular code from the frontend encodes the request URL that is sent out to the AWS API Gateway but I get the following error.
`The Canonical String for this request should have been
'GET
/data/23/hello/Sayr%2520Hi`
My API gateway has a velocity template the decodes the parameters using $util.urlDecode()
I'm facing the same problem.
I've been stuck for a day.
If you are using HttpApi it cannot be solved.
Nevertheless, if you use RestApi I managed to make this work.
Specifically, you should use the URL Path Parameters.
You should:
Add a resource containing the /{variable}
Add a Url Path Parameter in the Integration Request Configuration with name variable and mapped from method.request.path.variable
Notice that the solution may depend on the integration type that you are using.
In the screenshot below you can see how I'm redirecting all the received traffic to a NetworkLoadBalancer.
The resource has the variable /{proxy+}, the endpoint URL has the {proxy}, and, in the URL Path Parameters, I've configured the mapping method.request.path.proxy.

AWS API Gateway integration request Http headers not being passed to lambda

This is similar to this post API-Gateway Integration Request HTTP Header not mapping query string to header but I can't see any answer for it and all of the answers are not related to what the question is intended.
I am trying to add the integration request parameters in API Gateway, but whenever I set 'Http Headers' as shown here and 'Mapping template' as passthrough, I could not see that header when I log inside the lambda.
Also in the integration response I cannot reference it inside the integration header response parameters. The "integration.response.header.cokers" will be returned blank when I invoke the API. This is how I configured the integration response
Ultimately the solution here is to implement a lambda proxy integration.
A proxy integration in API Gateway tells API Gateway to simply forward all headers to the integration for processing, which means you will see all of those values in your lambda function.
NOTE: Lambda has to return a specific response format back to API Gateway if it's a proxy integration. Ultimately, the response should be something like:
{
'statusCode': 200,
'headers': {
'echo-proxy': True
},
'body': 'some payload'
}
What you are trying to do right now is map everything manually, which is a deprecated approach and usually you don't want to do that unless you absolutely have to because it's kind of a pain.
If you have to map the headers manually start by mapping them in the the method request so it can carry on to the next step and so on. Basically like this:
Method Request -> Maps variable to Integration Request -> Maps variable to Body Mapping Template -> Maps variable to actual request header
What you have in your screenshot for the Integration Request -> HTTP Headers is:
Name: cokers
Mapped from: 'blah'
However, "mapped from" should look something like "method.request.header.coker" which is a standardized path (meaning to get the value from the Method Request Header field with name "coker").
Once you have added the coker header to the Method Request, and the Integration Request HTTP Headers are mapped correctly, you have to implement a mapping template. Set the content-type to application/json with passthrough set to "When there are no templates defined(recommended)" and a simple mapping template:
{
"headers": {
"coker" : "$input.params('coker')"
}
}
That is the way my API is setup and it returns the following to me because I had my lambda function return the event as a json object back to API GW:
{"body": "{\"headers\": {\"coker\": \"mapped\"}}", "statusCode": 200}
NOTE: the value of my header "coker" in the request on the client side is "mapped"
UPDATED ANSWER
To map the original "coker" header to "coker2" (or any other name you want to give it) you simply set the name of the header in your mapping template like so:
{
"headers": {
"coker2" : "$input.params('coker')"
}
}
Then edit your lambda function to return "coker2" header and you should get a response like this:
{"body": "{\"headers\": {\"coker2\": \"mapped\"}}", "statusCode": 200}

return a 302 from AWS API Gateway using request path

I have a simple site running on Lambda, using a single proxy resource in API Gateway to route requests to it.
I'm trying to set up some "vanity URLs": someone arriving on /somepath should be redirected to /?source=somepath.
I'm trying to achieve this in API Gateway rather than passing it through to the Lambda app to manage.
I've set up a resource on /somepath, with a Mock integration type.
The Method Response contains only a 302 type, which contains a Location response header.
The Integration Response contains a corresponding 302 response type
The Header Mappings contain a Location header mapped to context.resourcePath
This works, sort of. A request to /somepath returns a 302 response with a Location header value of /somepath.
But how can I format that Header Mapping value to be (i.e.):
/?source=${context.resourcePath}
Is there a way I can do this all in API Gateway, using only a Mock endpoint instead of passing the request through to an actual integration backend to return a header value?

How to bypass header from request into header in response in AWS API Gateway?

I have API Gateway endpoint, which is actually mock endpoint.
What I am trying to do is to make API to take Origin header from request and return the same value in response as Access-Control-Allow-Origin header.
So far I've tried to do the following:
Got to "Method Request" and add "Origin" header to the list
In "Method Execution" I am trying to map Access-Control-Allow-Origin to method.request.header.Origin, but I am getting an error message
Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: method.request.header.Origin]
Thanks!
integration.request and integration.response only prepare the input to and output from the integration response. Therefore the integration request only supports additional input from the method.request and the integration response only supports additional input from the method response definitions.
Mapping the method.request parameters to method.response is currently not supported but definitely a valid and useful use case. I'll add it to our backlog, but unfortunately cannot commit to a timeline for when we plan on delivering this feature enhancement.
As a workaround, you could pass the Origin header to your integration endpoint which simply mirrors the input and passes it back to API Gateway. This way you should be able to return the value of the Origin request header as an Access-Control-Allow-Origin response header.
Hope this helps,
Jurgen, API Gateway
It can be done by input.param and context.responseOvverride methods
In Integration Response add a Mapping Template for proper Content-Type with a body like this:
#set($origin = $input.params('origin'))
#set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)
It should look like this:
Of course, it can also be added via Cloud Formation and x-amazon-apigateway-integration. Example part of yaml:
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseTemplates:
application/json: |
#set($origin = $input.params('origin'))
#set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)
Hope that helps.