Node.js + Express + simpledb; "TypeError: Cannot read property 'Errors' of null" when trying to list domains - node.js

I'm trying to get a very simple test of Amazon SimpleDB running with Node.js/Express. This is the code I'm using (AWS key/secret sanitized, of course):
var express = require('express');
var simpledb = require('simpledb');
var app = express.createServer();
var sdb = new simpledb.SimpleDB(
{keyed:'MYKEY', secret:'MYSECRET'}, simpledb.debuglogger);
app.get('/', function(req, res) {
console.log("about to list domains...");
sdb.listDomains(function(error, result, meta) {
console.log("listing domains, I think?");
});
});
app.listen(8888);
This is the error I'm getting:
DEBUG: simpledb: 2012-04-06T01:34:24.856Z create {"keyid":"MYKEY","secret":"MYSECRET","secure":false,"consistent":true,"test":false,"maxtry":null,"expbase":null,"delaymin":null,"delayscale":null,"randomdelay":null} {"secure":false,"host":"sdb.amazonaws.com","path":"/","version":"2009-04-15","port":80}
about to list domains...
DEBUG: simpledb: 2012-04-06T01:34:29.253Z request 1333676069253 ListDomains {}
DEBUG: simpledb: 2012-04-06T01:34:29.387Z handle 1333676069253 ListDomains {"Action":"ListDomains","Version":"2009-04-15","SignatureMethod":"HmacSHA256","SignatureVersion":"2","Timestamp":"2012-04-06T01:34:29.253Z","AWSAccessKeyId":"MYKEY","Signature":"AWSSIGNATURE"} 1 false null
/home/rob/node_modules/simpledb/lib/simpledb.js:136
if( res.Errors ) {
^
TypeError: Cannot read property 'Errors' of null
at [object Object].handle (/home/rob/node_modules/simpledb/lib/simpledb.js:136:12)
at /home/rob/node_modules/simpledb/lib/simpledb.js:188:18
at Parser.<anonymous> (/home/rob/node_modules/simpledb/node_modules/aws-lib/lib/aws.js:81:13)
at Parser.emit (events.js:67:17)
at Object.onclosetag (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/xml2js/lib/xml2js.js:120:24)
at emit (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/sax/lib/sax.js:148:32)
at emitNode (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/sax/lib/sax.js:152:3)
at closeTag (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/sax/lib/sax.js:226:5)
at Object.write (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/sax/lib/sax.js:567:29)
at Parser.<anonymous> (/home/rob/node_modules/simpledb/node_modules/aws-lib/node_modules/xml2js/lib/xml2js.js:145:29)
I'm pretty new to Node.js, the simpledb module and SimpleDB itself, but this to me seems like a bug in the simpledb module. I can't figure out what I'm doing wrong otherwise - I'm confident my key/secret are valid (as I've tested with both set invalid, separately and together, and I get back actual errors from Amazon that indicate the key/secret are invalid).
This error, though, has me stumped. Any ideas?

This turned out to be a dependency issue in the simpledb node module:
Hi - this seems to have been caused by the latest version of a
dependent lib - I've rebuilt and publish a new version 0.0.8 - please
let me know if this works - thanks!
Source. It has since been fixed.

FYI - Since your original post, AWS has published their official SDK for Node.js. http://docs.aws.amazon.com/nodejs/latest/dg/nodejs-dg-examples.html
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
var db = new AWS.SimpleDB();
db.client.listDomains(function(error, data) {
if (error) {
console.log(error);
} else {
console.log(data);
}
});

Related

npm connect-multiparty 'TypeError: Cannot read properties of undefined (reading 'path')' on AWS Elastic Beanstalk

The connect-multiparty package is giving me some trouble; When I'm running my website locally, it works perfectly fine, saves the uploaded multiform data as intended, but when running on AWS Elastic Beanstalk, I run into the error TypeError: Cannot read properties of undefined (reading 'path')
The first bit of my backend code is here:
const multipart = require('connect-multiparty')
consts.mainRouter.post(`/*`, mpmw, (req, res, next) => {
index.log(`mainRouter got posted in uploads: ${req.url}`)
next()
})
consts.mainRouter.post(`${prefix}`, mpmw, async (req, res) => {
index.log(`upload request received`)
const account_data = await consts.accountExists(req.signedCookies)
console.log(req.body)
console.log(req.files)
let { audio, thumbnail } = req.files
let { name, collab } = req.body
let imageblobin = fs.readFileSync(`${thumbnail.path}`)
let imageblob = undefined
let imagebloblarge = undefined
let newtime = new Date().getTime()
On the "fs.readFileSync()" line, the error occurs; What could go wrong on AWS Elastic Beanstalk here that would work fine on my local machine?
Note: I am 100% sure that the request was correctly made, it previously worked, and only the backend was changed since
Turns out there was something wrong with the EB environment I was using (sadly don't know what); I swapped the backend to a different environment which isn't blocking my multipart/form-data requests and therefore doesn't bring this error.

AWS Greengrass V2 Node Publishing problem with aws-iot-sdk-v2 JS

For the past few days I've been trying to solve the problem of publishing a message from Lambda to the AWS cloud, using Greengrass v2.
The code in python was even provided in the documentation, only had to be slightly reworked.
When it comes to SDK v2 JS in documentation there is only minimal mention about publish function in AWS-CRT library.
I tried to create code using components from this library, but it looks like the library also requires a script with parameters.
This is my code that requires installation of aws-iot-sdk-v2 js.
const iotsdk = require("aws-iot-device-sdk-v2");
const mqtt = iotsdk.mqtt;
const os = require("os");
const util = require("util");
const GROUP_ID = process.env.GROUP_ID;
const THING_NAME = process.env.AWS_IOT_THING_NAME;
const THING_ARN = process.env.AWS_IOT_THING_ARN;
(topic = "gg/message"),
(payload = JSON.stringify({ message: util.format("ping") }));
function greengrassHelloWorldRun() {
mqtt.MqttClientConnection.prototype.publish(topic, payload);
}
console.log(topic);
console.log(payload);
setInterval(greengrassHelloWorldRun, 5000);
exports.handler = function (event, context) {
console.log("event: " + JSON.stringify(event));
console.log("context: " + JSON.stringify(context));
};
I get errors about arguments and NAPI.
The same errors also appear when using this function as lambda component in greengrass logs
Maybe someone has some example how to publish some message on topic using Node lambda with sdk v2.
After contacting AWS Support I know it is impossible.
AWS doesn't support mqttProxy IPC for SDK V2 JS yet.
ChristopherTal
I'm also using the Greengrass SDKs for JS and indeed they're still a work in progress. But I was able to send messages to the IoTCore from Greengrass using the JS SDKs.
A few things to mention:
You seem to use the aws-iot-device-sdk-v2 SDK which is for things
The aws-greengrass-core-sdk npm package is made for components
It is important to differ between things and components and decide who's doing what.
To send data to IoTCore from a thing, you need indeed to use MQTT. On the deployment page on the Greengrass console, you need to revise the deployment and add following components:
MQTT Broker
MQTT Bridge
Client device auth
This way your thing connects to the local MQTT Broker through the client device auth component and the MQTT Bridge decides how the traffic is routed. You can read all info on the links above.
I even realised this using the standard mqtt npm package. You need to create a certificate and a thing using lambda or the console and use those certificates to access the broker.
const mqtt = require('mqtt')
const fs = require('fs')
const ca = fs.readFileSync(locationOfTheCA)
const key = fs.readFileSync(locationOfThePrivateKey)
const cert = fs.readFileSync(locationOfTheCertificate)
console.log('Welcome to MQTT Connector')
const client = mqtt.connect('mqtts://localhost:8883', {
clientId: 'yourThingNameHere',
ca: ca,
key: key,
cert: cert
})
client.on('connect', function () {
console.log('Connected to MQTT')
/* client.subscribe('$aws/*', function (err) {
if (!err) {
//client.publish('presence', 'Hello mqtt')
}
})*/
})
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
client.end()
})
Hopefully this helps you out!
Warm regards
Hacor

Different Behavior Deploying AWS Lambda Standalone vs within an Application Stack

Hi everybody and thanks for taking time to look at my issue/question.
I am getting different results when deploying my AWS Lambda stand-alone versus within an Application Stack.
I'm trying to connect to AWS Elasticache Redis from within my Lambda. I have .Net Core 3.1 Lambdas (using StackExchange.Redis) which can connect. But I also need to be able to connect from my Node.js Lambdas.
For the Node.js Lambdas, I'm using "node-redis" and "async-redis". I have two Lambdas which are essentially identical except that one is deployed in an Application Stack and the other is deployed as a stand-alone Lambda. Both Lambdas reference the same Lambda Layer (i.e. same "node_modules"), have the same VPC settings, the same Execution Role, and essentially the same code. So they've pushed it up to another group.
The stand-alone Lambda connects to Redis without issue. The Application Stack Lambda does not and exits processing before completing but without raising any error.
At first I thought I might just need to configure my Application Stack but I cannot find any information indicating we even can configure Application Stacks. So I'm at a loss.
The stand-alone Lambda:
exports.handler = async (event) => {
const asyncRedis = require("async-redis");
const redisOptions =
{
host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
port: 6379
}
console.log('A');
const client = asyncRedis.createClient(redisOptions);
console.log(client);
console.log('B');
const value = await client.get("Key");
console.log('C');
console.log(value);
console.log('D');
console.log(client);
};
The output of this function is essentially:
A
{RedisClient} --> the "client" object --> Shows connected = false
B
C
{ Correct Data From Redis }
D
{RedisClient} --> the "client" object --> Shows connected = true
The Application Stack Lambda:
async function testRedis2(event, context) {
console.log('In TestRedis2');
const asyncRedis = require("async-redis");
const redisOptions =
{
host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
port: 6379
}
console.log('A');
const client = asyncRedis.createClient(redisOptions);
console.log(client);
console.log('B');
var value = await client.get("Key");
console.log('C');
console.log(value);
console.log('D');
console.log(client);
}
module.exports = {
testRedis2
};
The output of this function is essentially:
In TestRedis2
A
{RedisClient} --> the "client" object --> Shows connected = false
B
I don't understand why these don't perform identically. And I don't get why I don't see further entries in the output.
Has anyone else experienced issues connecting to VPC resources from within an Application Stack?
Thanks
I stumbled across the answer through extensive trial and error. It may be obvious to Node/js developers but, just in case another Javascript/Node newbie has the same issue, I'll post the answer here.
The import/require and creation of the client must be at the top of the module. Not in the function itself.
So, the following does work in my application stack:
const asyncRedis = require("async-redis");
const redisOptions = {
host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
port: 6379
};
const client = asyncRedis.createClient(redisOptions);
async function redisGet(key: string){
// console.log('In redisGet');
return await client.get(key);
}

Error: GoogleMapsAPI is not defined for node-googlemaps

I am using node-googlemaps to query the Google Maps API from Node js. I have created my Server API key as a Developer. According to the this documentation, I have to make a publicConfig variable with my API key and certain other parameters. My publicConfig variable is as follows:
var gm = require('googlemaps');
var publicConfig = {
key: 'myKey',
stagger_time:1000, // for elevationPath
encode_polylines:false,
secure:true // use https
};
var gmAPI = new GoogleMapsAPI(publicConfig);
When I run the Code, I get the following error
ReferenceError: GoogleMapsAPI is not defined
Can somebody help me on this issue?
To Resolve this issue I had include the following line of Code
var GoogleMapsAPI = require('googlemaps');

How can I set up logging for node-mongod-native?

I am trying to set up logging for the native mongo driver for node. I've got the following snippet set up as a demonstration for what I am trying to do. Unfortunately nothing is being emitted on the console. Any ideas?
var express = require('express') ;
var app = express();
var http = require('http');
var mongod = require('mongodb');
var server_conf = new mongod.Server('localhost', 27017, {auto_reconnect:true});
//dummy logger
var logger = {
error:function(message, object) {console.log('anything')},
log:function(message, object) {console.log('anything')},
debug:function(message, object) {console.log('anything')}}
var db_container = {db: new mongod.Db('test', server_conf,
{w:1,journal:true, native_parser:true, logger: logger})}
app.use(express.bodyParser());
app.use(app.router);
db_container.db.open(function(err, index_info){
if(err) throw err;
var testcol = db_container.db.collection('testcol');
app.get('/', function(request, res){
testcol.insert({hello:"moto"}, function(err,doc){
if(err){
throw err;
}
testcol.find({}).toArray(function(err,docs){
res.send(docs);
});
});
});
http.createServer(app).listen(3000, function () {
console.log('Express server listening on port ' + '3000');
});
});
Replicated below is: a copy of the answer to this question I posted on the node-mongodb-native google group
After looking at the most recent version of the code (commit 0fd78b3278da8deac980cb876fcb2bf72eaafb79) it looks like logging isn't really implemented yet.
First some ground rules: If you create a server config object (http://mongodb.github.io/node-mongodb-native/api-generated/server.html?highlight=server#Server) and set the logger object there that's ok. If you create a Db() object and set a logger in its options then it will override any logger you have set its server config. If you create a MongoClient() object this is equivalent to new Db('test', serverOptions, options) so you can set your logger object in either serverOptions or options. I'm not going to cover MongoClient.Connect and what happens there because I don't care to look over that portion of the code.
I could only find usage of the logger object happening in connection.js where it's revealed that you actually need a few additional properties to get logging working.
i.e line 69
if(this.logger != null && this.logger.doDebug){
this.logger.debug("opened connection", this.socketOptions);
}
or line 307
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
There are many more doDebug/doError property lookups in connection.js that require logging to work. There is a very minimal amount of logging happening from the looks of it but if you want to enable it you need to set the doError/doLog/doDebug properties on your logger as well. I actually haven't tested this out since I don't have the proper setup here but from looking over the code this seems to be the case.

Resources