Is there a way to map all parameters,headers and body to the other http endpoint? does it require a special template?
This is what I've got so far:
functions:
myfunction:
handler: lambda.myfunction # dummy hanlder
events:
- http:
path: resource/{resourceId}/other
method: get
integration: HTTP
request:
uri: http://url/resource/{resourceId}/other
parameters:
'method.request.path.resourceId': true
'method.request.header.my-header': true
response:
statusCodes:
200:
pattern: ''
Whenever i create directly in the console the the passthrough option is enabled by default and it maps the resourceId correctly.
I tried to look into the documentation but seems that there's almost no documentation on the http integration, unless i'm missing something.
Is there a way to map all parameters,headers and body to the other http endpoint? does it require a special template?
Yes, use HTTP_PROXY integration type. In the console this is a checkbox in the Integration Request page.
I was able to find a workaround to have this working, seems more a workaround than the correct solution.
I had to set the Integration.RequestParameters in the resources of the serverless.yml to achieve this.
resources:
Resources:
ApiGatewayMethodV1ResourceResourceidVarOtherGet:
Properties:
RequestParameters:
method.request.path.resourceId: true
method.request.header.my-header: true
Integration:
RequestParameters:
integration.request.path.resourceId: method.request.path.resourceId
integration.request.header.my-header: method.request.header.my-header
Related
I have a simple lambda function setup with a serverless.yml configuration. What I'm looking to do is to have an additional lambda function which would be called for OPTIONS method for any of the deployed lambda functions. For example, if /login is called with OPTIONS I want options handler to handle the execution. If /login is called with GET I want the actual login handler to handle the execution. Same for all the other handler functions as well.
Serverless.yml
functions:
login:
handler: handler.login
events:
- http:
path: login
method: get
stats:
handler: handler.Stats
events:
- http:
path: patientset/{id}/stats
method: get
options:
handler: handler.options
events:
- http:
path: '/' //Need something global like this
method: options
Handler.js
module.exports.options = (event) => {
const headers = setHeaders(event);
return {
statusCode: 200,
headers,
body: JSON.stringify({})
}
}
//Code updated in edit
login:
handler: handler.login
events:
- http:
path: login
method: get
cors:
origin: 'https://d2mo71maq8qx66.cloudfront.net'
headers: ${self:custom.ALLOWED-HEADERS}
allowCredentials: true
If I understand you correctly, then you have to combine the handler functions and handle the differentiation between GET and OPTIONS within your Lambda function's code. At the moment your code does not work properly because you are creating three different Lambda functions and three different REST APIs (where one REST API is integrated with one Lambda function). This is a problem because each REST API has a different endpoint url. So you have http://api-A.../login, http://api-B.../patientset/{id}/stats and http://api-C.../ as your endpoints. In order to call one endpoint with different HTTP methods like GET or OPTIONS, you need to define it like this:
functions:
login:
handler: handler.myHandler
events:
- http:
path: '/login'
method: get
- http:
path: '/login'
method: 'options'
This will produce an endpoint like http://api-X.../login that you can either call with GET or OPTIONS. When you receive the event in your myHandler function, you need to decide on the httpMethod parameter of the event object which code you want to execute.
However, this seems to be not enough for you because you want this for any deployed Lambda function. Unfortunately, I'm not aware of a way to automatically do this for every deployed Lambda function. As far as I know, you need to explicitly add an options event as above to every endpoint/Lambda function that you have in your Lambda function and adjust your handler functions appropriately.
Besides that, you don't need to write an options event for each path. You can also use {proxy+} for the options event instead. For example:
events:
- http:
method: 'options'
path: '/{proxy+}'
A side note on this topic: If you're doing all of this because you want to return some CORS headers, then you should consider using the cors option instead. This usually reduces the amount of config + code you have to write.
In serverless.yml, under custom, I have the following code (with dummy values here):
customDomain:
domainName: myhost.mydomain.com
basePath: ''
stage: ${self:provider:stage}
createRouteS3Record: true
endpointType: 'edge'
securityPolicy: tls_1_2
certificateArn: 'arn:aws:acm:.................'
hostZoneId: 'P4OCK4S1PSTZK'
when I execute serverless deploy, everything goes smooth. the Api get generated properly for my function.
(Under functions i have events: http)
However after the API getting generated lambda getting deployed, I get the following error:
Error: Error: Unable to setup base domain mappings for myhost.mydomain.com
i do not get much info other than https://forum.serverless.com/t/error-unable-to-setup-base-domain-mappings/11395
Do not know how to include api versions in serverless if that is the solution.
Well small things can cause big problems and are very hard to figure out at times.
I found that stage: ${self:provider:stage} was wrong, it should have been stage: ${self:provider.stage}. The colon after provider was the culprit.
I got this error after having a domain mapping, then removing it, then trying to add it again: it looks like Serverless doesn't completely remove a domain mapping.
I had to go to Custom domain names -> my domain -> API mappings -> Configure API mappings and manually delete the domain mapping before redeploying.
Had the same issue. In my serverless.yml file in events inside functions I was having 'httpApi'. Changing it to 'http' fixed my issue
functions:
getWebHooks:
handler: src/path
events:
- httpApi:
path: /
to
functions:
getWebHooks:
handler: src/path
events:
- http:
path: /
I was getting that error message because I (somehow) got the same api duplicated. so I went to
API Gateway -> Custom domain name -> {name_of_my_domain} -> API Mappings -> Configure API Mappings
Then I changed the API to use the correct API (holding the routes I was having in my app, and I could differentiate between both using their ID). Redeploying with Serverless succeeded
I'm pretty excited about HTTP Gateways due to the drastically reduced pricing in comparison to REST Gateways, but I'm stuck on creating routes that do not completely blow up my serverless.yml file.
The documentation for HTTP Gateway at Serverless describes this to define routes:
functions:
params:
handler: handler.params
events:
- httpApi:
method: GET
path: /get/for/any/{param}
There is a support for '*', but this causes issues with OPTIONS cause those will overwrite the created CORS policies (so OPTIONS requests would actually get to the application, which does not make any sense, especially if the route is protected via an authorizer).
Also, it's not possible to define multiple methods.
# does not work
method: GET,POST,DELETE
# also not possible
method:
- GET
- POST
- DELETE
The only configuration I found is to define all routes separately:
events:
- httpApi:
path: /someApi/{proxy+}
method: GET
- httpApi:
path: /someApi/{proxy+}
method: POST
- httpApi:
path: /someApi/{proxy+}
method: DELETE
This works fine & the UI is even bundling the routes cause they're on the same prefixed path:
But with this I have to define all HTTP methods for all my main resources separately including the attached authorizer.
Is there some way to combine this?
In my project i have the following function:
createSite:
handler: CreateSite.main
events:
- http:
path: sites
method: post
cors: true
authorizer: aws_iam
but is it possible to have another post function directed at the same dynamodb but with different attributes etc. Because if I make another post method how do i specify which one to call?
Yes, you can have another post method directed at the same backend system with different attributes but you need to map that post method with a different http path. It will look something like this:
createSite:
handler: CreateSite.main
events:
- http:
path: sites_v2
method: post
cors: true
authorizer: aws_iam
Though i have a question:
If both the post methods are going to interact with same table in DynamoDB, then why not merge these two post methods/APIs into a single API which contain the extra attributes as optional and can function if any of those attribute is provided by the client.
The only reason you'd want to have separate post methods/APIs even if they are interacting with same DynamoDB table, if these operations interact with other external services based on different attributes and requires different scaling.
I'm trying to add CORS header to Method Response header with serverless. Here's my config:
- http:
path: /myapi
method: GET
cors: true
My expectation is that CORS is enabled in GET method, but only OPTION method comes up. From my research, I stumbled upon this setting:
- http:
path: /myapi
method: GET
cors: true
"responseModels": {"application/json": "Empty"}
"statusCode": "200"
"responseParameters": {"method.response.header.Access-Control-Allow-Origin": true}
However nothing showed up and no error when I deployed serverless. My understanding is that a 200 response status code has to exist before CORS can be added here. When I create a new resource using UI console, a 200 status code is added automatically but serverless doesn't create it.
Any suggestion to achieve this without me creating a 200 status code manually?
This should work. I do this every day. I use Python, I set the CORS to true in serverless.yml and also must explicitly, manually, set the Access-Control-Allow-Origin to * in every response. Maybe that is not ideal, but it works for us.