AWS Lambda: module initialization error: Error when running Camaro/Serverless - node.js

I've created a lambda function handler in NodeJS with Serverless. When I use the command: serverless offline start, I don't get any error. However when I want to deploy the app with the command serverless deploy, it deploys fine. When I want go to the endpoint, I'm getting an internal server error, this happens only when I require camaro in my application. I need the camaro library to create a template from XML.
I tried using node 6.10 and remove camaro, and install it with node 6.10. This doesn't make a difference.
This is the error I can view in Cloud watch:
module initialization error: Error at Error (native) at
Object.Module._extensions..node (module.js:597:18) at Module.load
(module.js:487:32) at tryModuleLoad (module.js:446:12) at
Function.Module._load (module.js:438:3) at Module.require
(module.js:497:17) at require (internal/module.js:20:19) at
Object. (/var/task/node_modules/camaro/index.js:4:16) at
Module._compile (module.js:570:32) at Object.Module._extensions..js
(module.js:579:10)
This is my index.js
const serverless = require('serverless-http');
///
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
//serverless
module.exports.handler = serverless(app);
This is my serverless.yml
# serverless.yml
service: lambda-dashboardcb
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: eu-west-1
functions:
app:
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
plugins:
- serverless-offline
This is my package.json
package.json
{
"name": "lambda-dashboardcb",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon ./bin/www"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.17.1",
"body-parser": "^1.18.2",
"camaro": "^2.2.2",
"cookie-parser": "^1.4.3",
"debug": "~2.6.9",
"express": "^4.15.5",
"google-oauth-jwt": "^0.2.0",
"googleapis": "^23.0.0",
"morgan": "^1.9.0",
"pug": "^2.0.0-beta11",
"serve-favicon": "^2.4.5",
"serverless-http": "^1.5.2"
},
"devDependencies": {
"nodemon": "^1.13.3",
"serverless-offline": "^3.16.0"
}
}
Router
var express = require('express');
var router = express.Router();
var metadata = require('../public/javascripts/metadata-onix.js');
var path = require("path");
var app = express();
/* GET home page. */
router.get('/', function(req, res, next) {
res.sendFile(path.join(__dirname, '../public', 'index.html'));
});
router.param('isbn', function (req,res,next){
next();
});
router.get('/metadata:isbn', function(req,res,next){
/**
- Get ISBN From URL
- Get Metadata from ISBN, return as JSON
**/
var isbn = req.params.isbn;
var info = metadata.getMetadataOnix(isbn).then(function(info) {
res.json({ cover : info });
});
});
module.exports = router;
Module which uses Camaro
const axios = require('axios');
const transform = require('camaro');
exports.getMetadataOnix = function (id) {
/**
- Create template
- Get request to content CB API.
- Transform data with template.
- Return data.
**/
const template = {
template stuff...
}
return axios({
method: 'get',
url: 'APIURL'+id,
transformResponse: [function (data) {
"use strict";
data = transform(data, template);
return data;
}],
// No .catch here
}).then(function(resp){
console.log('Cover from book:'+JSON.stringify(resp.data));
return resp.data;
});
}

camaro is a native module. you will need to install correct prebuilt binary for AWS Lambda.
Even though you switch to Node 6.10 locally but the binary installed on your machine is built for your platform only, which maybe different with the platform on AWS Lambda.
In order to use camaro on AWS Lambda, you should download a copy of prebuilt camaro from Releases and put to this folder path node_modules/camaro/lib/binding/camaro.node.
As of currently, AWS Lambda only supports node 6 on Linux so you're looking for camaro-v2.1.0-node-v48-linux-x64.tar.gz.
Lambda already supports Node 8 now so choose the prebuilt binary accordingly.

Related

How to fix middleware function error app.use

I already installed Express, Nodeman, Express-Edge. I using Windows 10.
Someone who had a similar problem with me was told that he needed to install the library he had specified. Like I said I already installed it.
in index.js codes;
const path = require('path');
const expressEdge = require('express-edge');
const express = require('express');
const app = new express();
app.use(express.static('public'));
app.use(expressEdge);
app.set('views', __dirname + '/views');
app.get('/', (req, res) => {
res.render('index');
});
app.get('/about', (req, res) => {
res.sendFile(path.resolve(__dirname, 'pages/about.html'));
});
app.get('/contact', (req, res) => {
res.sendFile(path.resolve(__dirname, 'pages/contact.html'));
});
app.get('/post', (req, res) => {
res.sendFile(path.resolve(__dirname, 'pages/post.html'));
});
app.listen(4000, () => {
console.log('App listening on port 4000')
});
command shell saying:
C:\Users\Maximus\WebstormProjects\untitled4\nodejs-blog-tutorial\node_modules\express\lib\application.js:210
throw new TypeError('app.use() requires a middleware function')
^
TypeError: app.use() requires a middleware function
at Function.use (C:\Users\Maximus\WebstormProjects\untitled4\nodejs-blog-tutorial\node_modules\express\lib\application.js:210:11)
at Object.<anonymous> (C:\Users\Maximus\WebstormProjects\untitled4\nodejs-blog-tutorial\index.js:8:5)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
[nodemon] app crashed - waiting for file changes before starting...
package.json
{
"name": "nodejs-blog-tutorial",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"keywords": [
"blog"
],
"description": "",
"dependencies": {
"express": "^4.17.1",
"express-edge": "^2.0.2",
"nodemon": "^2.0.4",
"startbootstrap-clean-blog": "^5.0.9"
}
}
It appears you aren't using the right export from the express-edge library. Per the documentation, it should be this:
const express = require('express');
const expressEdge = require('express-edge');
const app = new express();
app.use(expressEdge.engine);
Or, you could do it like this:
const express = require('express');
const { config, engine } = require('express-edge');
const app = new express();
app.use(engine);
The idea here is that expressEdge exports an object that has two properties config and engine and you have to access those properties in order to use the library properly.

Mikronode with Express Js: TypeError: _sentence$.get(...).do is not a function

I want to use Mikronode with Express Js but get an error TypeError: _sentence$.get(...).do is not a function for the first run.
I generate the application skeleton using Express generator and try the example Mikronode code from wiki.mikrotik.com
This is the code:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var api = require('mikronode');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Mikronode example code
var connection = new api('192.168.0.1','admin','password');
connection.connect(function(conn) {
var chan=conn.openChannel();
chan.write('/ip/address/print',function() {
chan.on('done',function(data) {
var parsed = api.parseItems(data);
parsed.forEach(function(item) {
console.log('Interface/IP: '+item.interface+"/"+item.address);
});
chan.close();
conn.close();
});
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
If i run the code above, the output show an error:
/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:474
_parsed$.set(this, _sentence$.get(this).do(function (d) {
^
TypeError: _sentence$.get(...).do is not a function
at new SocketStream (/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:474:52)
at MikroNode.connect (/Users/me/Desktop/mknode/node_modules/mikronode/dist/mikronode.js:330:30)
at Object.<anonymous> (/Users/me/Desktop/mknode/app.js:31:12)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Module.require (module.js:587:17)
at require (internal/module.js:11:18)
error Command failed with exit code 1.
My package.json:
{
"name": "mknode",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"core-decorators": "^0.20.0",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"mikronode": "^2.3.11",
"morgan": "~1.9.0",
"pug": "2.0.0-beta11",
"rxjs": "^6.2.2"
}
}
Anyone can help me to solve this?
solved by installing "rxjs": "^5.3.0"

Deployment of Nodejs Code with Google Cloud

I am trying to deploy my webapp code built on NODE JS. I deployed a simple application hello-world from
https://github.com/GoogleCloudPlatform/nodejs-docs-samples/tree/master/appengine/hello-world
and it worked.
Attached is my project structure.
In the client folder i have angular4 where the build files will be stored in public
In the server folder i have defined routes.
This setup is working find on my local. No errors.
But when i deploy it on google cloud i am getting
Error: Server Error
The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.
and error log says
Error: No default engine was specified and no extension was provided.
at View (/app/server/node_modules/express/lib/view.js:61)
at EventEmitter.render (/app/server/node_modules/express/lib/application.js:570)
at ServerResponse.render (/app/server/node_modules/express/lib/response.js:1008)
at (/app/server/app.js:42)
at Layer.handle_error (/app/server/node_modules/express/lib/router/layer.js:71)
at trim_prefix (/app/server/node_modules/express/lib/router/index.js:315)
at (/app/server/node_modules/express/lib/router/index.js:284)
at Function.process_params (/app/server/node_modules/express/lib/router/index.js:335)
at next (/app/server/node_modules/express/lib/router/index.js:275)
at Layer.handle_error (/app/server/node_modules/express/lib/router/layer.js:67)
Can anyone guide me on why this error?
My root package.json file to run npm start is
{
"name": "test-application",
"description": "A simple application for testers who run",
"version": "0.0.1",
"private": true,
"license": "Apache-2.0",
"author": "Alaksandar Jesus Gene",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">=4.3.2"
},
"scripts": {
"deploy": "gcloud app deploy",
"start": "node server/app.js"
},
"dependencies": {
},
"devDependencies": {
},
"cloud-repo-tools": {
"test": {
"app": {
"msg": "Hello, world!"
}
},
"requiresKeyFile": true,
"requiresProjectId": true
}
}
And my app.yaml file is
# [START app_yaml]
runtime: nodejs
env: flex
skip_files:
- ^client$
# [END app_yaml]
Point to note, both files were copied from google sample github project and added values.
Project Folder Structure - Expanded
Project Folder Structure - Collapsed
Can anyone guide me on why this error?
Fixed it. My mistake in app.js coding
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
const http = require('http');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var api = require('./routes/api');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../public')));
app.use('/api', api);
app.get('*', (req, res) => { //i think the issue was here. I had app.use
res.sendFile(path.join(__dirname, '/index.html'));
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`Running on localhost:${port}`));
module.exports = app;

NodeJS. Cannot read property of undefined

Have a problem with using another method in class.
I'm working with express framework and have to use Ecma Script 6.
When I try to use method in the same class I have an error:
Cannot read property 'generatePassword' of undefined
TypeError: Cannot read property 'generatePassword' of undefined
at createUser (E:\OpenServer\domains\testNode\app\controllers\users.js:5:13)
at Layer.handle [as handle_request] (E:\OpenServer\domains\testNode\node_modules\express\lib\router\layer.js:95:5)
at next (E:\OpenServer\domains\testNode\node_modules\express\lib\router\route.js:131:13)
at Route.dispatch (E:\OpenServer\domains\testNode\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (E:\OpenServer\domains\testNode\node_modules\express\lib\router\layer.js:95:5)
at E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:277:22
at Function.process_params (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:330:12)
at next (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:271:10)
at Function.handle (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:176:3)
at router (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:46:12)
My code:
Route: /routes/users.js
const express = require('express');
const router = express.Router();
const users = require('../app/controllers/users');
router.get('/', users.createUser);
module.exports = router;
Controller: /app/controllers/users.js
class Users
{
createUser(req, res)
{
this.generatePassword();
res.json({msg: "The method return user data" });
}
generatePassword()
{
return 'The method return new password';
}
}
module.exports = new Users();
Main App file: /app.js
const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const index = require('./routes/index');
const users = require('./routes/users');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
package.json
{
"name": "testnode",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.15.2",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"express": "~4.14.0",
"hbs": "~4.0.1",
"morgan": "~1.7.0",
"serve-favicon": "~2.3.0"
}
}
Help me please, thank you.
In the line that causes the error, the object this is not what you think it is. To solve this, replace the following:
router.get('/', users.createUser);
with:
router.get('/', users.createUser.bind(users));
This will make sure when eventually that function is called by the router.get implementation, it will be called with the this object set to users.

Auto reload with supervisor in express.js

My package.json
{
"name": "lays-vroubek",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "supervisor ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"jade": "~1.11.0",
"less-middleware": "^2.0.1",
"morgan": "~1.6.1",
"reload": "^0.7.0",
"serve-favicon": "~2.3.0",
"supervisor": "^0.9.1"
}
}
My app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var lessMiddleware = require('less-middleware');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public'), {
force: true,
debug: true,
once: false
}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
I run my app with comand: "$ DEBUG=lays-vroubek:* npm start" but auto-reload does not work without any error msg (app runs)
lays-vroubek#0.0.0 start /Users/jan.michalik/Workspace/Sites/lays-vroubek
supervisor ./bin/www
Running node-supervisor with
program './bin/www'
--watch '.'
--extensions 'node,js,/bin/www'
--exec 'node'
Starting child process with 'node ./bin/www'
Watching directory '/Users/jan.michalik/Workspace/Sites/lays-vroubek' for changes.
Press rs for restarting the process.
lays-vroubek:server Listening on port 3000 +0ms
Any help?
For example, you have an express app named backend. Than you can use
DEBUG=backend:* supervisor -w server -e ejs,js,json bin/www
to autorestart express app if any of ejs, js or json files is changed inside server dir (usual, i place my express app into server dir)

Resources