I am using the #aws-sdk/client-lambda npm package for invoking lambdas. I have two Lambdas. Lambda A & Lambda B. Lambda A is trying to invoke Lambda B.
Lambda A invokes Lambda B by running the following code:
const { LambdaClient, InvokeCommand } = require('#aws-sdk/client-lambda');
module.exports = {
getGitHubToken: async () => {
const client = new LambdaClient({ region: process.env.REGION });
const params = {
FunctionName: process.env.GITHUB_TOKEN_FUNCTION,
LogType: 'Tail',
Payload: '',
};
const command = new InvokeCommand(params);
try {
const { Payload } = await client.send(command);
console.log(Payload);
return Payload;
} catch (error) {
console.error(error.message);
throw error;
}
},
};
The expected response from Lambda B should look like this:
{
statusCode: 200,
body: JSON.stringify({
token: '123',
}),
};
However, Payload looks to be returning this from the line console.log(Payload);:
I looked on the AWS SDK Website and it looks like Payload returns a Uint8Array. I guess this is because it's from a promise?
I have tried doing Payload.toString() however that comes back as simply a string of the values in the Unit8Array. Example being:
2021-04-13T14:32:04.874Z worker:success Payload: 123,34,115,116,97,116,117,115,67,111,100,101,34,58,50,48,48,44,34,98,111,100,121,34,58,34,123,92,34,116,111,107,101,110,92,34,58,92,34,103,104,115,95,111,114,101,51,65,109,99,122,86,85,74,122,66,52,90,68,104,57,122,122,85,118,119,52,51,50,111,67,71,48,50,75,121,79,69,72,92,34,125,34,125
My Question:
How do I resolve data from Unit8Array to the data I was expecting from the Lambda response? Which is a JSON Object?
I have confirmed the requested Lambda (Lambda B in this case) is returning the data correctly by going to CloudWatch. Thanks.
Okay, I found a way to get this working.
You have to specify a text encoder:
const asciiDecoder = new TextDecoder('ascii');
Then decode it so it looks like this:
const data = asciiDecoder.decode(Payload);
I have logged an issue on their repository asking why this isn't included in the module. I will post an update on any movement on this.
I am using AWS Lambda and I have 2 functions within my handler.js file. I want to call the one function (getClient) within the other function. The problem I am having is that the first function (getClient) needs query string parameters and I don't know how to attach that when calling the function.
I have tried changing the event object that is sent to the function and adding the query string parameter as a json but that doesn't work.
let json = JSON.parse(event.body);
event = {
emailAddress: json.clientEmailAddress
}
var client = this.getClient(event);
console.log(client)
I get the error that queryStringParameter is undefined.
errorType": "TypeError",
"errorMessage": "Cannot read property 'queryStringParameters' of undefined",
To invoke an AWS Lambda function from another function, I would suggest to use the AWS SDK and use the invoke API call.
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property
Invoke is taking an PayLoad parameter that can contain any object.
For example :
try {
const lambdaParams = {
FunctionName: 'my-lambda',
// RequestResponse is important here. Without it we won't get the result Payload
InvocationType: 'RequestResponse',
LogType: 'Tail', // other option is 'None'
Payload: queryStringParameters
};
const lambda = new AWS.Lambda({region: 'eu-west-1', apiVersion: '2015-03-31'});
const const lambdaResult = await lambda.invoke(JSON.stringify(lambdaParams.Payload)).promise();
logger.debug(`Lambda returned : ${lambdaResult.Payload}`);
const resultObject = JSON.parse(lambdaResult.Payload)
} catch (e) {
console.error(e);
}
I am trying to deploy a GraphQL server on node.js platform using Azure functions. I have been able to deploy a basic hello world app.
However, I need to get data from a backend API in the resolver. I am not able to get either fetch or request package to work in Azure functions.
Below is my code:
var { graphql, buildSchema } = require('graphql');
var fetch = require('node-fetch');
var request = require('request');
var schema = buildSchema(`
type Query {
myObject: MyObject
}
type MyObject {
someId (data: String) : String
}
`);
var root = {
myObject: () => {
return {
someId: (args) => {
// Code enters till this point.
// I can see context.info messages from here.
// return "hello"; <--- This works perfectly fine.
return request('http://example.com', function (error, response, body) {
// -----> Code never enters here.
return body;
});
}
}
}
};
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
graphql(schema, req.body, root)
.then(response => {
context.res = {
body: JSON.strigify(response)
};
context.done();
});
};
I have tried using fetch and request modules. But with both of them, I see the same behavior - the response never returns. The request eventually times out after 5 minutes. If instead of fetch or request, I choose to return some dummy value, I see the response getting returned correctly to the query. With fetch, I don't see the then block or the catch block ever executing.
Note: I have tried both http and https URLs in the request URIs but none of them seem to return any data.
Is it an issue with the way I have implemented the fetch/request or is it an issue with Azure functions in general?
Answering my own question:
It seems that node-fetch and request don't actually return promises. Wrapping the request around Promise seems to solve the problem. Something similar to this answer.
I am trying to access a Lambda function using a POST method. When I try to test the POST resource I put in the Request body {"article_url": "http://technewstt.com/bd1108/"}
This makes the API Gateway respond with Execution failed due to configuration error: Malformed Lambda proxy response My code is below.
exports.handler = (event, context, callback) => {
//event = {"article_url": "http://technewstt.com/bd1108/"};
console.log(event.article_url);
var http = require('http');
var TextAPI = require('textapi');
var textapi = new TextAPI({
application_id: "randomn numbers",
application_key: "randomn numbers"
});
textapi.summarize({
url: event.article_url,
sentences_number: 3
}, function(error, response) {
if (error === null) {
response.sentences.forEach(function(s) {
console.log(s);
//var body = JSON.parse(s);
// TODO implement
//callback(null, s);
callback(null, {"statusCode": 200, "body": JSON.stringify(s)});
});
}
});
};
Please note that if I uncomment the second line the API gateway works fine.
Any help with this issue would be greatly appreciated.
You are using Lambda Proxy integration which always expects output of the format http://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
"Malformed Lambda proxy response" is returned if the lambda response format is unexpected. You can enable logging with full request/responses which should show you the response being returned from lambda. Its likely there was an error in you lambda function which returned an error.
UPDATE: I had a mistake on my http request endpoint. I had not set the appropriate authentication options so that fixed a lot of errors possibly this specific one.
My question is similar to one here:
Node.js Lambda function returns "The response is invalid" back to Alexa Service Simulator from REST call
However the solution to that question does not solve my problem. So I make an http request call to an xsjs service in Hana cloud. I am getting the 'response is invalid' error message. I can't see why. Here is my function:
// Create a web request and handle the response.
function httpGet(query, callback) {
console.log("/n QUERY: "+ query);
var host = 'datacloudyd070518trial.hanatrial.ondemand.com';
var path = '/LocationInformation/getLocationInfo.xsjs?location=';
var hostname = 'https://' + host + path + query;
var auth = 'user1:D1anafer';
var req = http.request({'hostname': hostname,
'auth': auth
}, (res) => {
var body = '';
res.on('data', (d) => {
body += JSON.stringify(d);
});
res.on('end', function () {
callback(body);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
}
And the function that calls it:
'getNewsIntent': function () {
//self = this;
httpGet(location, function (response) {
// Parse the response into a JSON object ready to be formatted.
//var output = JSON.parse(response);
//output = output['change'];
var output = response;
var cardTitle = location;
var cardContent = output;
alexa.emit(':tellWithCard', output, cardTitle, cardContent);
});
},
Thank You
-Diana
Inside your AWS account go to your Lambda function and click on the monitoring tab, where you should see "View Logs in Cloudwatch" in the right hand corner. If you click that link and you should see the errors that are being produced.
You can also use console.log() to log any information being returned from your REST api, which will be logged in cloudwatch and can help you see where your errors are.
This is just a guess from the top of my head. To really help some detailed error message would be required like mentioned about.
But just a guess: Your http.request() is using the http module (https://nodejs.org/api/http.html) and your are accessing the a https resource. If so there is a https (https://nodejs.org/api/https.html) module or use something like axios https://www.npmjs.com/package/axios or requestjs (https://github.com/request/request) this will handle both.
Like I said just a blind guess without detailed error message and seeing your require statements but I am happy to dive deeper if you happen to have details.
HTH
Your callback from the Lambda has to return a valid status code and body. Like this:
let payload = {
statusCode: 400,
body: JSON.stringify('body'),
headers: {"Access-Control-Allow-Origin": "*"}
};
callback(null, payload);
On top of that, to call this from client side code, you have to pass the CORS header back.