Scenario
My React (Gatsby) application requests information from a database to display a list of products.
The database is a Postgres table on AWS RDS, in a VPC.
My aim is for the React application to trigger an AWS Lambda function to retrieve products from AWS RDS.
Error:
In writing my lambda function, I intend to request all products from my table.
The error message I get is TypeError: Wrong arguments
Code:
index.js
const rds = require('./connection.js');
exports.handler = async ( event, context, callback ) => {
await callback(null, rds.getProducts);
};
connection.js
const Pool = require('pg').Pool;
const pool = new Pool({
user: process.env.user,
host: process.env.host,
database: process.env.database,
password: process.env.password,
port: process.env.port,
});
const getProducts = ( request, response ) => {
pool.query(`SELECT * FROM product_list ORDER by id ASC`, ( error, result ) => {
if( error ) throw new Error(error);
response.status(200).json(result.rows);
})
};
module.exports = {
getProducts,
};
package.json
{
"name": "lambda3",
"version": "1.0.0",
"description": "lambda function access rds",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "scott",
"license": "ISC",
"dependencies": {
"pg": "^7.14.0"
}
}
Full error:
{
"errorType": "TypeError",
"errorMessage": "Wrong arguments",
"trace": [
"TypeError: Wrong arguments",
" at RAPIDClient.postInvocationResponse (/var/runtime/RAPIDClient.js:41:18)",
" at complete (/var/runtime/CallbackContext.js:34:12)",
" at callback (/var/runtime/CallbackContext.js:44:7)",
" at /var/runtime/CallbackContext.js:105:16",
" at Runtime.exports.handler (/var/task/index.js:9:11)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
Thoughts: I followed the AWS guide on how to upload a NodeJS deployment package. There didn't seem to be an issue with connection.js when testing locally.
Unsure how to debug this as even "AWS Lambda wrong arguments" yields few relevant results.
What I see as the main issue here is how you use the call back.
The callback function accepts two parameters error and the value.
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
What I think that you are doing wrong here is, passing the function as reference instead of value for e.g rds.getProducts() to get the value.
Related
Setting up an AWS Lambda Layer in NodeJS.
The steps are clear.
Setup the following directory structure:
-layer
utils.js
-nodejs
package.json
package-lock.json
-node_modules
The utils file has a simple piece of code in it, like this:
export function get_exchange_rate(curr1, curr2){
return 100.00;
}
The package.json file contains this:
{
"name": "layer",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "utils.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
}}
I zip up everything inside the layers folder and upload to Lambda Layers.
I attach the layer to the Lambda and my Lambda handler looks like this:
'use strict';
const opps = require('/opt/utils');
exports.handler = function(event, context) {
console.log("EXCHANGE RATE: ", opps.get_exchange_rate(1,2).toString())
};
I run it and it works fine.
But then I add an NPM module to the layer. I run npm install request, this adds request and dependencies to the node_modules folder and updates the packages.json file with the request dependency.
"dependencies": {
"request": "^2.88.2"
}
And in the utils.js file I add the following code:
import request from 'request'
export function get_status(){
request("http://www.google.com", (error, response, body) => {
console.log("error:", error);
console.log("statusCode:", response && response.statusCode);
console.log("body:", body);
});
}
I zip this all up and add to Lambda Layers, then call the get_status() function from Lambda, I receive this error:
SyntaxError: Cannot use import statement outside a module
i am trying to connect mssql database but i couldnt achieve that.
When i connect mssql on Microsoft SQL Server Management Studio 18;
https://i.stack.imgur.com/6xdI0.png -- Because of Windows Authentication, i have no password. And there is a username field passive as default, also node js doesnt accept default user name. Why? and what i am doing wrong? When i try to execute js file; https://i.stack.imgur.com/Ty0zA.png -- gives an user name error in cmd db.js file;
var sql = require('mssql');
// config for your database
var config = {
user: 'DESKTOP-S9H932R\\CUNEYT',
password: '',
server: 'localhost',
database: 'cuneyt'
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from borsa', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
package.json file;
{
"name": "mssql_test",
"version": "1.0.0",
"description": "",
"main": "db.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mssql": "^6.3.1"
}
}
OP solved but for anyone having trouble my issue was that I was connecting to a local DB within a domain. I had to add the option to my config object to be like
config:{
user:'xxxx',
password:'xxxx',
server:'servername',
database:'yourdb'
domain:'yourdomainname'}
I have a frontend in react-native that makes an API call using the axios library; its shown below:
function addItem(item) {
if (!item) {
Alert.alert('Error', 'Please enter a valid item.', [{text: 'Ok'}]);
} else {
axios.get('/additem', {
Id: items[items.length - 1].id + 1,
Text: item
})
.then((res) => {
setItems([...items, {id: res.id, text: res.text}])
})
.catch((err) => {
console.log(err);
})
}
}
As you can see, I am making a GET request to an endpoint, and using the response data.
Here is what my backend endpoint looks like in Node.js (using Express.js):
app.get('/additem', (req, res) => {
const item = new Item({
id: req.body.Id,
text: req.body.Text
});
item.save()
.then((result) => {
res.send(result)
})
.catch((err) => {
console.log(err)
})
})
The save() function and Item object are just specific to MongoDB, so don't worry too much about that.
I am using a proxy to "connect" the backend and frontend, meaning, I have added this to my package.json file in my frontend:
{
"name": "firstProj",
"version": "0.0.1",
"private": true,
"proxy": "https://localhost:5000",
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
localhost:5000 is where my node.js backend is running
Now when I try to access the endpoint via my frontend, react-native yells at me saying this:
LOG [Error: Network Error]
Zero clue why this is happening. Any help is appreciated. :) Let me know if you need more information from my end.
Thanks a ton.
EDIT:
this is the full error when not caught by my code:
Possible Unhandled Promise Rejection (id: 0):
Error: Network Error
createError#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:99656:26
handleError#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:99560:27
dispatchEvent#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:32348:31
setReadyState#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:31432:33
__didCompleteResponse#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:31248:29
emit#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:3537:42
__callFunction#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2765:36
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2497:31
__guard#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2719:15
callFunctionReturnFlushedQueue#http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2496:21
callFunctionReturnFlushedQueue#[native code]
just Remember to not put http://localhost:PORT into API Address because it will not work in that way
the way you should do it is first find your internet IP address on your machine like :
108.67.122.124
and then you change setting in your backend Service and replace localhost with this :
108.67.122.124:PORT
and then Address it like that to your AXIOS or whatever library you use
So lets wrap it again :
DONT address your react native like http:localhost:5000 instead do it like 108.67.122.124:5000 In that way it will fully work
I am trying to set up testing for my puppeteer project. I was following a basic guide and the test passes but there is 2 console errors in the terminal.
The error doesn't show up when using https://google.com or https://youtube.com. So it looks like it could be a thing with the specific site?
console.error
Unhandled error
at process.uncaught (node_modules/jest-jasmine2/build/jasmine/Env.js:248:21)
at handler (node_modules/jest-environment-puppeteer/lib/PuppeteerEnvironment.js:17:11)
at map (node_modules/mitt/src/index.ts:74:75)
at Array.map (<anonymous>)
at Object.emit (node_modules/mitt/src/index.ts:74:56)
at Page.emit (node_modules/puppeteer/lib/EventEmitter.js:72:22)
console.error
at process.uncaught (node_modules/jest-jasmine2/build/jasmine/Env.js:249:21)
at handler (node_modules/jest-environment-puppeteer/lib/PuppeteerEnvironment.js:17:11)
at map (node_modules/mitt/src/index.ts:74:75)
at Array.map (<anonymous>)
at Object.emit (node_modules/mitt/src/index.ts:74:56)
at Page.emit (node_modules/puppeteer/lib/EventEmitter.js:72:22)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.613 s
Ran all test suites.
Here is my code
describe('NCAA Home', () => {
beforeAll(async () => {
await page.goto('http://stats.ncaa.org/rankings/change_sport_year_div');
});
it('should be titled "NCAA Statistics"', async () => {
await expect(page.title()).resolves.toMatch('NCAA Statistics');
});
});
Here is my jest.config.js
module.exports = {
preset: "jest-puppeteer",
testMatch: [
"**/test/**/*.test.js"
],
verbose: true
}
package.json
{
"name": "stackoverflow",
"version": "1.0.0",
"description": "",
"main": "index.js",
"jest": {
"preset": "jest-puppeteer"
},
"scripts": {
"test": "jest"
},
"author": "",
"license": "ISC",
"devDependencies": {
"jest": "^26.1.0",
"jest-puppeteer": "^4.4.0"
},
"dependencies": {
"puppeteer": "^5.1.0"
}
}
All of the things I have come across have mentioned an issue with async/await but anything I have tried produces the same, if not, more errors. I have made a new project with these files and I am getting the same error
The error is from the website itself. Check the console of the website. Hence for a websites like google.com or youtube.com, it works without any errors.
I have created clean repo which reproduces issue.
https://github.com/sergtimosh/jest-puppeteer-issue-reproduction.git
clone repository
npm i
npm test test.spec.js
or
HEADLESS=false npm test test.spec.js
A workaround is to create incognito browser context in jest-environment.js.
Just uncomment two lines in this file and tests are passing with no issues. But problem is still here if you need to share browser context between test suites(files).
const PuppeteerEnvironment = require('jest-environment-puppeteer');
class JestEnvironment extends PuppeteerEnvironment {
async setup() {
await super.setup()
//to fix issue uncomment next two lines
// const incognitoContext = await this.global.browser.createIncognitoBrowserContext()
// this.global.page = await incognitoContext.newPage()
}
async teardown() {
await super.teardown()
}
}
module.exports = JestEnvironment;
I have been unsuccessful in trying to figure out how to solve the following errors, (1st error:)'OPTIONS http://localhost:3000/lists/5a9dca48cebb5a4e5fc1bfe9 404 (Not Found)' and (2nd error:)'Failed to load http://localhost:3000/lists/5a9dca48cebb5a4e5fc1bfe9: Response for preflight has invalid HTTP status code 404.'.
Initially I defined my code along the same lines as the following: https://github.com/20chix/Hotel_System_Vue.js_Frontend/blob/master/src/components/Hello.vue
Seen quite a number of posts similar to my problem, but neither of their suggested solutions have worked for me.
I'm using Vue.js, Axios and Node.js in the back, my collection is defined as follows in MongoDb:
List: {_id:'', name:'', items:
[ {
title: '',
category: ''
}
]
}
GetList.vue:
methods: {
fetchLists(){
let uri = 'http://localhost:3000/lists';
axios.get(uri).then((response) => {
this.List = response.data;
console.log(this.List[3].items[0]);
console.log(this.List);
});
},
DELETE(a_list, id){
$("#myModal").modal('show');
this.list = a_list;
this._id = id;
},
deleteList : function(_id){
// let uri = 'http://localhost:3000/lists/'+_id;
// this.List.splice(_id, 1);
axios.delete('http://localhost:3000/lists/'+_id)
.then((response) => {
this.fetchLists();
//refreshes Application
// window.location.reload();
})
.catch((error) => {
console.log(error);
});
}
ListController:
exports.delete_a_list = function(req, res)=>{
console.log(req.params);
List.deleteOne({req.params.listId}, function(err, list){
if(err){res.json(err);};
else
{res.json({list: 'List successfully deleted'});}
};
});
UPDATE:
Upon running 'npm install cors --save', it was stored in my package.json .
server/package.json:
{
"name": "api",
"version": "1.0.0",
"description": ":)",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [
":)"
],
"license": "ISC",
"devDependencies": {
"nodemon": "^1.17.1"
},
"dependencies": {
"cors": "^2.8.4",
"express": "^4.16.2",
"mongoose": "^5.0.8",
"npm": "^5.7.1"
}
}
UPDATE:
I tried the following too:
ObjectID = require('mongodb').ObjectID;
exports.delete_a_list = function(req, res){
// console.log(req.params);
List.deleteOne({
_id: ObjectID(req.params.listId)}, function(err, list){
if(err)
res.json(err);
res.json({list: 'List successfully deleted'});
});
};'
This returns the same error including:
xhr.js?ec6c:178 OPTIONS http://localhost:3000/lists/undefined 404 (Not Found)
dispatchXhrRequest # xhr.js?ec6c:178
xhrAdapter # xhr.js?ec6c:12
dispatchRequest # dispatchRequest.js?c4bb:59
Promise.then (async)
request # Axios.js?5e65:51
Axios.(anonymous function) # Axios.js?5e65:61
wrap # bind.js?24ff:9
deleteList # GetList.vue?c877:131
boundFn # vue.esm.js?efeb:190
click # GetList.vue?d584:124
invoker # vue.esm.js?efeb:2004
fn._withTask.fn._withTask # vue.esm.js?efeb:1802
:1 Failed to load http://localhost:3000/lists/undefined: Response for preflight has invalid HTTP status code 404.
createError.js?16d0:16 Uncaught (in promise) Error: Network Error
at createError (createError.js?16d0:16)
at XMLHttpRequest.handleError (xhr.js?ec6c:87)
Thank you guys for all your suggestions.
I found the following video: https://www.youtube.com/watch?v=NEFfbK323Ok, from The Net Ninja, and was able to get it to finally work upon changing my code to reflect his particular method:
listRoutes.js:
app.route('/lists/:_id')
.get(lists.read_a_list)
// .update(lists.update_a_list)
.delete(lists.delete_a_list);
listController.js:
exports.delete_a_list = function(req, res){
// console.log(req.params);
List.findByIdAndRemove({_id: req.params._id}).then(function(list){
res.send(list);
});
};
GetList.vue:
deleteList : function(_id, List){
axios.delete('http://localhost:3000/lists/'+_id, List)
.then(response => {
this.List.splice(index, 1);
//refreshes Application
// window.location.reload();
})
}
Your problem ist related to CORS (cross-origin-resource-sharing).
If you are using node with express then just include this middleware:
https://www.npmjs.com/package/cors
This query seems wrong:
List.deleteOne({req.params.listId}, ...
Can you try modifying it like this?:
List.deleteOne({_id: ObjectID(req.params.listId}), ...
(You need to have ObjectID declared somewhere up: ObjectID = require('mongodb').ObjectID)