Possible to have two post methods in the same app? - amazon-web-services

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.

Related

How to Add Resource with form-data Parameters in WSO2 API Manager?

I Have a REST API Which Takes two Parameters Like the Image Below:
And as You See This is form-data Parameters.
How can I Add This to API Manager?
In API Manager, from a UI perspective, we can only configure whether that particular API Resource requires a Body or Header. But, we can make use of the Swagger Editor to specify other fields.
I believe that your requirement is to show the mentioned two parameters as multipart/form-data properties in the Swagger UI. If so, make the following changes to the Swagger definition to display them (in Devportal). Assuming that you are using API Manager 3.x series, I have provided the Swagger snippet related to the OpenAPI definition
openapi: 3.0.1
...
paths:
/*:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
param1:
type: string
param2:
type: object
format: binary
...
Hope this helps you to achieve your requirement.

AWS Lambda: how to have multiple handlers for same path?

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.

Error Unable to setup base domain mappings for serverless custom domain

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

AWS HTTP Gateway: Multiple Methods for same Route excluding OPTIONS with Serverless Framework

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?

API Gateway configure http integration with input passthrough serverless 1.x

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