Deployment of Nodejs Code with Google Cloud - node.js

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;

Related

HPM Error occurred while trying to proxy request in Heroku

I get this error: [HPM] Error occurred while trying to proxy request /api/artefact from myapp.herokuapp.com to http://localhost:5000 (ECONNREFUSED) when I deploy my MERN app.
These are the relevant files in terms of proxying and deploying:
setupProxy.js
const proxy = require("http-proxy-middleware");
module.exports = app => {
app.use(proxy("/api/", { target: "http://localhost:5000" }));
};
server.js
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const logger = require("morgan");
const { mongo_uri } = require("./config/config");
const path = require("path");
let cors = require("cors");
const PORT = process.env.PORT || 5000;
const app = express();
app.use(cors());
// Set up Routes
const artefactRoutes = require("./routes/api/artefact.js");
const userRoutes = require("./routes/api/users.js");
const authRoutes = require("./routes/api/auth.js");
// Connect to MongoDB Database
const dbRoute = mongo_uri;
mongoose
.connect(dbRoute, { useNewUrlParser: true })
.then(() => console.log("Connected to Database"))
.catch(err => console.log(err));
// Body Parser Middleware to parse request body into readable json format
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Used for logging
app.use(logger("dev"));
app.use("/api", artefactRoutes);
app.use("/api/users", userRoutes);
app.use("/api/auth", authRoutes);
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../client/build")));
app.get("*", (req, res) => {
// relative path
res.sendFile(path.join(__dirname, "../client", "build", "index.html"));
});
}
app.listen(PORT, () =>
console.log(`Static server has started. Listening on port ${PORT}`)
);
static.json (though I'm not sure really what this does as I just found someone do this on another thread but it didn't change anything for me)
{
"root": "build/",
"clean_urls": false,
"routes": {
"/**": "index.html"
}
}
and my scripts in the parent directory package.json
"scripts": {
"start": "concurrently \"cd backend && node server.js\" \"cd client && npm start\"",
"format": "prettier",
"heroku-postbuild": "cd client && npm install && npm run build"
},
and it might help to mention that my folder structure is like:
-/project
--/client
--/backend
Basically the problem I'm having is that I've deployed my react app to heroku and the frontend loads fine, but none of the axios api calls to my backend are returning anything and just give me a 504 timeout error, and in the heroku logs it just says the proxy error. Any help would be much appreciated!

AWS Lambda: module initialization error: Error when running Camaro/Serverless

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.

Node (Express) / React app only works locally

Issue Outline
I have a simple Node / React app, which runs fine using heroku local.
The Node backend has an /api/users endpoint, which returns some hardcoded JSON.
After heroku local, visiting localhost:5000/users works as expected, displaying the hardcoded users as per the Users.js React component.
However, when pushed to Heroku, only the / root page works. Going to /users shows Not Found, and going to /api/users returns the JSON.
I'm not sure why it works locally and not on Heroku, any help is appreciated.
Code
Express routes:
var express = require('express');
var router = express.Router();
var path = require('path');
router.get('/api/users', function(req, res, next) {
res.json([{id: 1, name: 'Colin'}, {id: 2, name: 'Spodie'}])
});
module.exports = router;
The Express app.js file:
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 cors = require('cors');
var config = require('./config/dev')
var index = require('./routes/index');
var app = express();
app.use(cors())
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// serve static files from React
app.use(express.static(path.join(__dirname, '../frontend/build')));
// 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;
React App.js file:
import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
import Users from './Users';
import NotFound from './NotFound';
import Home from './Home';
class App extends Component {
state = {users : []}
render() {
return (
<div>
<Switch>
<Route exact path='/' component={Home}/>
<Route exact path='/users' component={Users}/>
<Route component={NotFound} />
</Switch>
</div>
);
}
}
export default App;
React api.js file:
const api = process.env.BACKEND_URL || 'http://localhost:5000'
export const getUsers = () => (
fetch(`${api}/api/users`)
.then(res => res.json())
)
React package.json
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.12"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000"
}
Screenshots
Home page running locally
Home page running on Heroku
Users page running locally
Users page running on Heroku
You are serving static files but you also need to forward all HTTP GET requests to client side react router so it can handle. You may want to put this route to your app.js:
app.get("*", function (req, res) {
res.sendFile(__dirname + "/path/to/index.html")
})

Issues deploying NodeJS w/ MongoLab on Heroku

I'm having issues deploying my app on Heroku. I keep getting a screen in my browser saying Application Error. From what i've read this is something with MongoLab.
I have set my PROCESS.ENV.MONGOLAB_URI correctly on heroku and I can't get it to work. I have also tried adding a new user to MongoLAB for this DB and even that user won't work as well.
I am Process.env.PORT because I am using Socket.io. Is it something in my app.js?
var express = require('express');
var http = require('http')
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/queueThat');
var db = mongoose.connection;
var routes = require('./routes/index');
var app = express();
var server = http.createServer(app);
//Stuff for Sockets
var io = require('socket.io').listen(server);
//sockets
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require('ejs').renderFile);
// 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('/', routes);
//Connect to the Socket
io.on('connection', function(socket){
socket.on('song send', function(song){
io.emit('song send', song)
console.log('artist on')
})
socket.on('artist send', function(artist){
console.log('artist on')
io.emit('artist send', artist)
})
//Disconnect
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
// 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: {}
});
});
var port = (process.env.PORT || 8000);
server.listen(port, function() {
console.log("Listening on " + port);
});
module.exports = app;
I have also tried adding my node and NPM versions to no avail. Any ideas? Package.json looks like this.
{
"name": "queueThat",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "^2.3.4",
"express": "~4.13.1",
"mongoose": "*",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"socket.io": "*"
},
"engines": {
"node": "5.4.0",
"npm": "3.3.12"
}
}
Application Error doesn't mean that there is something wrong with MongoLAB, not necessarily.
To be clear you need to double check few places:
You need to have proper Procfile in the root folder of your project
Be aware of postinstall npm script.
Also you could check your logs on heroku heroku logs -n 200 (200 or more lines if needed) to be sure what's the problem you have.

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