How log an HTTP JSON request in Loopback app deployed on Heroku? - node.js

An app (Loopback) is deployed on Heroku, and I need to to see the req body (the JSON) send to this app for debugging purpose.
So the access to the log is :
heroku logs --tail
The server.js is like the following :
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
console.log('Web server listening at: %s', app.get('url'));
});
};
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
app.start();
});

As loopback extends express, we can use body parser module. So first install "body-parser"
Then add this code in serveur.js
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
var logger = function(req, res, next) {
console.log(JSON.stringify(req.body, null, 2));
next(); // Passing the request to the next handler in the stack.
}
app.use(logger);
...
The remote log will display every request body received by the server.

If you don't want to modify your server.js file (and why would you), you can register a middleware logging all requests, refer to:
https://docs.strongloop.com/display/public/LB/Defining+middleware#Definingmiddleware-Overview
for more detail on how to register and write a middleware. routes:before would be a good phase to log requests.

Related

node and express error "cannot GET /" even after I included app.get() in my server.js

I am trying to start my project via launching server.js but I am getting error:"cannot GET /"
even after I made an app.get() route in my server.js
I am using also "body-parser" as a middleware, and "cors"
server.js:
// Setup empty JS object to act as endpoint for all routes
const projectData = {};
// Require Express to run server and routes
const express = require('express');
// Start up an instance of app
const app = express();
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const cors = require('cors');
app.use(cors());
// Initialize the main project folder
app.use(express.static('views'));
const port = 8080;
app.use(express.static('dist'));
// Setup Server
const server=app.listen(port, ()=>{console.log(`running on localhost: ${port}`)});
app.get('/all', sendData);
function sendData (request, response) {
response.send(projectData);
};
// TODO-ROUTES!
app.post('/add', Info);
function Info(req, res) {
projectData['date'] = req.body.date;
projectData['temp'] = req.body.temp;
projectData['content'] = req.body.content;
res.send(projectData);
}
module.exports = server;
I made a POST request to /add and it works. Then I call GET /all and also work. The error cannot GET / is because you are requesting an endpoint that not exists.
Just add a dummy data to your Fn() if you want to see some output on GET request wihtout making any post request
Here is my solution
app.get('/', (req, res) => {
res.redirect('/all');
})
we need this because you do not have any root URL set, so we set the root URL to redirect to /all
2nd step then we add a dummy data in the projectData
var projectData = {
date = new Date().getDate();,
temp = 10,
content="This is Test Content"
}
This way when you call 'http://localhost:8080/' you shall get redirected to http://localhost:8080/all and instead of empty {} you shall see the dummy data.

Can't fetch the authorization code after the redirect url

I am working on Salesforce and Slack integration. And I don't know much about javascript and its related technologies. Could you please look into the code and let me know whats missing?
// Import express and request moduless
var express = require('express');
var request = require('request');
var url = require('url');
var clientId = '****';
var clientSecret = '****';
var SF_LOGIN_URL = "http://login.salesforce.com";
var SF_CLIENT_ID = "****";
// We define the port we want to listen to. Logically this has to be the same port than we specified on ngrok.
const PORT=4390;
// Instantiates Express and assigns our app variable to it
var app = express();
app.enable('trust proxy');
//var server = http.createServer(app);
//Lets start our server
app.listen(PORT, function () {
//Callback triggered when server is successfully listening.
console.log("Example app listening on port " + PORT);
});
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
// Route the endpoint that our slash command will point to and send back a simple response to indicate that ngrok is working
app.post('/oauth', function(req, res) {
oauth(req, res);
});
function oauth(req, res){
res.redirect(200, `${SF_LOGIN_URL}/services/oauth2/authorize?response_type=code&client_id=${SF_CLIENT_ID}&redirect_uri=****/oauth&display=touch}`);
console.log(url.location.href);
}
It looks to me like you're redirecting an authorization request to Salesforce, and asking Salesforce.com (SFDC) to redirect it back to ****/oauth (from the redirect_uri= query parameter to the SFDC URL.
Are you hoping it will get redirected back to your own /oauth endpoint?
If so, it's possible SFDC is redirecting it with a GET operation rather than a POST operation. Be aware that the parameters to a GET show up in req.params rather than req.body.
Try implementing a get() handler to see if you get something workable.
app.get('/oauth', function(req, res) {
console.log ('GET /oauth', req.params)
/* do something here */
});

Nodejs post empty object

I simply make a ajax call to certain method in nodeJs app, and expected to log all parameters to see pass data properly. but since I post this its not..
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// set the port of our application
var port = process.env.PORT || 8080;
app.set('view engine', 'ejs');
// make express look in the public directory for assets (css/js/img)
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());
app.get('/', function(req, res) {
// ejs render automatically looks in the views folder
res.render('index');
});
app.listen(port, function() {
console.log('Our app is running on http://localhost:' + port);
});
'use strict';
app.post('/sendMail', function(request, response) {
console.log(request.body)//returns {} but why its empty?
})
and here is ajax call;(I validate paramters exist in headers via dev console)
constructor() {
this.message={
email:"",
message:""
}
}
#action postData() {
$.ajax({
url:"http://localhost:8080/sendMail",
ContentType:'application/json',
dataType:'json',
type:'post',
data:{body:this.message},
success:(result) =>{
},
EDITED: I am able to see data in log if I make a post request via POSTMAN I choose content-type:application/json and added raw json string "{'message':'hello world'}" and I saw in nodejs log its passed successfully whats wrong with my ajax call here ?
It's empty because your using specifying the request should contain a JSON body but don't actually send JSON, your sending an object.
In your ajax request, Change this line
data:{body:this.message}
to
data: JSON.stringify(this.message)

How to access the raw body of the request before bodyparser?

I am writing a custom middleware that generates a cryptographic signature of every request (it is very similiar to the authentication mechanism used by AWS API v4). In order for this signature to be correctly generated, I must fetch the entire raw body of the HTTP request.
I am also using BodyParser, which is registered after my custom middleware.
My custom middleware can be represented like this:
// libs/simplifiedSignatureCheckerMiddleware.js
module.exports = function (req, res, next){
// simple and fast hashing stuff
var payload = '';
req.on('data', function(chunk) { payload += chunk }, null);
req.on('end', function(){
// hmac stuff
console.log(payload);
var ok = true; // ...
if(ok)
next();
else
next("Bad")
});
}
This is how I use it on the server.
// simpleServer.js
// BASE SETUP
// =============================================================================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var jsonStream = require('express-jsonstream');
var nconf = require('nconf');
var https = require('https');
var fs = require('fs');
// load configurations
nconf.argv().env();
nconf.file({file: 'config.json'});
app.use(require('./libs/simplifiedSignatureCheckerMiddleware'));
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(jsonStream());
// ROUTES FOR API
// =============================================================================
var router = express.Router();
router.post('/api/', function (req, res) {
var param1 = req.body.param1 || "";
var param2 = req.body.param2 || "";
res.json({message: 'welcome', one: param1, two: param2 });
});
// REGISTER ROUTES
app.use(router);
// START THE SERVER
// =============================================================================
https.createServer({
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
}, app).listen(nconf.get('http:port'));
console.log("APIs listening on port " + nconf.get('http:port'));
As you can verify, the raw body is written successfully to the console by the middleware, BUT the request will never be processed by the registered route and the connection hangs forever.
Do you have any clue on how to solve this problem?
Thanks in advance.
Ok, since the only feasible way to solve this problem seems to be by modifying the original source code of bodyParser, I have forked it.
https://github.com/emanuelecasadio/body-parser-rawbody
This fork exposes the raw body of the request as a field named rawBody. As you can see, there is only ONE extra line of code.
You can install it by using npm install body-parser-rawbody.
EDIT
Another option is to use the bodyParser like this, as noted by dougwilson here: https://github.com/expressjs/body-parser/issues/83#issuecomment-80784100
app.use(bodyParser.json({verify:function(req,res,buf){req.rawBody=buf}}))
I haven't personally tried this option and I do not know if it works.

Two apps in expressjs

I am building an app with express js which will have different clients like web and mobile. I didnt want to use one app for both as some middleware would be additional burden. For say like session middleware. So is it possible for one project to have two apps. And how would it work?
The app object that you make in express is a function(req,res,next) that is suitable for Express's own middleware chains. So you can use app.use to send requests matching a leading path fragment to an app defined elsewhere.
Docs: http://expressjs.com/api.html#app.use
$ npm install express
//mobile.js
var app = require('express')();
app.get('/', function(req, res){
res.send('Mobile Route')
});
module.exports = app;
//desktopApp.js
var http = require('http');
var express = require('express');
var desktopApp = express();
var mobileApp = require('./mobile.js');
desktopApp.use('/mobile', mobileApp)
desktopApp.use(desktopApp.router);
desktopApp.use(express.errorHandler());
desktopApp.get('/', function(req, res){
res.send('Desktop Route')
});
desktopApp.get('/mobile', function(req, res){
// Because Express respects the order that you set up the middleware chain,
// the mobileApp `/mobile` route gets first dibs to send a response or next()
res.send('Inaccessible Desktop Route')
});
desktopApp.get('/mobile/foobar', function(req, res){
// When mobileApp can't find any suitable route matching this path, it gives
// up, and desktopApp continues to pass the request down the middleware stack.
// It ends up matching this route, where we send a response
res.send('Desktop Route')
});
http.createServer(desktopApp).listen(3000, function(){
console.log('Listening on 3000');
});
// Results
$ curl localhost:3000/
Desktop Route
$ curl localhost:3000/mobile/
Mobile Route
See the vhost example on the express github repository.
You can have a "main" app, which routes the requests to one app or another. You should write a middleware to establish the conditions where one app or another are requested. express.vhost is a good example, but maybe you need other checks than the domain one.
main-app.js
(The file called to start the server.)
// load dependencies
var main = express();
main.use( express.vhost( 'mobile', require( './the-mobile-app' ) );
main.use( express.vhost( '*', require( './the-web-app' ) );
main.listen( /*...*/ )
the-mobile-app and the-web-app.js
var app = express();
//
// setup your application conf, middleware, and routes
//
module.exports = app;
I wanted to share a different approach that I used in a project recently:
function renderAppropriate(template1, template2){
return function(req, res){
if(req.session && req.session.mobileOn){
res.render(template1);
} else {
res.render(template2);
}
};
};
app.get('/', function(req, res, next){
// do some stuff
next()
}, renderAppropriate('someMobileTemplate', 'someDesktopTemplate')
);

Resources