0

I have node/express apis app. I deploy all apis in one AWS-lambda function using serverless framework.

For some reason, I want to call one of the API routes directly from/within AWS-lambda function.

Node/express serverless app

const express = require("express"); const awsServerlessExpress = require("aws-serverless-express"); const app = express(); const server = awsServerlessExpress.createServer(app) ... const pointsRoute = require("./src/routes/points.route"); ... app.use(`/api/v5.1/points`, pointsRoute); module.exports.handler = (event, context) => { awsServerlessExpress.proxy(server, event, context); } 

points.route.js

const express = require("express"); const router = express.Router(); const { postPoints } = require("../ctrls/points.ctrl.js"); router.route("/").post(postPoints); module.exports = router; 

points.ctrl.js

exports.postPoints = (req, res, next) => { console.log("hitting postPoints method"); ... ... } 

Calling /api/v5.1/points route from javascript directly.

const AWS = require("aws-sdk"); AWS.config.update({ accessKeyId: "id", secretAccessKey: "AccessKey", region: "region" }) const lambda = new AWS.Lambda(); export const invokeLambda = async (points: any) => { return lambda.invoke({ // pls NOTE it always make GET call by default FunctionName: 'my-lambda-fn', InvocationType: 'RequestResponse', Payload: JSON.stringify({ path: '/api/v5.1/points', body: JSON.stringify(points) }), }).promise(); } 

call invoke method

 const result = await invokeLambda(points); 

With above setup I used to get error that route doesn't exist because /api/v5.1/points is defined with POST method as above.

So what I did: I just added GET method to make sure it hits route with GET method. I updated router code as follow,

const express = require("express"); const router = express.Router(); const { postPoints, getPoints } = require("../ctrls/points.ctrl.js"); router.route("/").get(getPoints).post(postPoints); module.exports = router; 

In points.ctrl.js just added,

exports.getPoints = (req, res, next) => { res.status(200).send("points being sent !!!"); // this is hitting now with lambda.invoke } 

Now calling invokeLambda function as below,

 await invokeLambda(points); 

it returns,

{ "statusCode": 200, "body": "points being sent !!!", "headers": { "x-powered-by": "Express", "access-control-allow-origin": "*", "content-type": "text/html; charset=utf-8", "content-length": "33", "etag": "W/\"21-McMNImVhZFYtkiA9PATcy7GTuZU\"", "date": "Tue, 25 Apr 2023 11:12:15 GMT", "connection": "close" }, "isBase64Encoded": false } 

THEN question is HOW CAN I MAKE POST method call from lambda.invoke? so it can start hitting POST route.

FYI previous question : invoke lambda(node/express - serverless express route) from javascript(reactjs) using aws-sdk

I tried adding POST as below,

 return lambda.invoke({ FunctionName: 'my-lambda-fn', InvocationType: 'RequestResponse', httpMethod: "POST" // throws validation error http:{ method : "POST" // throws validation error Payload: JSON.stringify({ path: '/api/v5.1/points', body: JSON.stringify(points) }), }).promise(); 

Update after creating bounty

Pls check below relevant questions which I asked and didn't receive any answer. This question will help you understand other aspect of the question asked here.

  1. Asked below question after this question.

Invoking Lambda function from JS doesn't receive payload/body/request object

  1. Asked below question before this question.

invoke lambda(node/express - serverless express route) from javascript(reactjs) using aws-sdk

14
  • By putting POST somewhere in the payload. The lambda service does not care about your REST API and the HTTP verbs you use in it. docs.aws.amazon.com/apigateway/latest/developerguide/… - I am surprised it actually works with the path top level in the payload. Commented Apr 25, 2023 at 11:53
  • outside Payload object, I tried with httpMethod:"POST" or http:{method:"Post"} but then it throws some validation error and doesn't make request. I really don't know what to add, where to add ? Commented Apr 25, 2023 at 11:57
  • No, inside the payload because as I said: Lambda does not care about http verbs and your REST api. Actually the request against lambda is always a POST but that is unrelated to what the request actually contains. Try printing the event to see what it normally contains to understand the difference between invoking the lambda and what the lambda actually is invoked with. Commented Apr 25, 2023 at 11:59
  • event object contains payload object only. In other words, path and body only. Commented Apr 25, 2023 at 12:03
  • I tried with method: "POST" inside payload, it still calls GET method. Commented Apr 25, 2023 at 12:18

1 Answer 1

3

Your httpMethod should be in payload instead, something like:

lambda.invoke({ FunctionName: 'my-lambda-fn', InvocationType: 'RequestResponse', Payload: JSON.stringify({ path: '/api/v5.1/points', body: JSON.stringify(points), httpMethod: "POST" }), }).promise(); 
Sign up to request clarification or add additional context in comments.

19 Comments

I think I already tried it but I can re-try and update you.
I believe you tried method instead of httpMethod, but let me know ;)
It looks to be hitting the POST method. Thanks a lot. However, I still get weird object in request object in POST method. It is almost exactly like stackoverflow.com/questions/43669913/node-js-how-to-inspect-request-data as mentioned in above one of the comments. Could you pls help to resolve that small part and I will be more than happy to accept your answer.
FYI, in my real app, I already use const bodyParser = require('body-parser'); app.use(bodyParser.json({ strict: false })); app.use(express.json()); app.use(express.urlencoded({ extended: true }));. I will try to change the value from false to true.
@micronyks what's wrong with your request object exactly? Possibly you need to send the payload base64 encoded..
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.