I need to create a NodeJS application which serves only for exposing REST APIs. When I created a ExpressJS project using Express generator express myNodeApp, it creates a project defaulting the view to .jade files.
Can I create and run a NodeJS project without views ? My NodeJS project will expose REST services which another client application will consume. Hence my NodeJS project do not need any UI elements. Also what package.json or .bin/www file will have. I will be hosting my NodeJS project in Azure cloud and my client application will consume the exposed service from cloud.
For an example see the code in this answer:
Node.js send data to backend with AJAX
Stripping all unnecessary code it would be basically:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/email', (req, res) => {
console.log(req.body.address);
res.json({ ok: true });
});
app.listen(4443, () => console.log('Listening on http://localhost:4443/'));
This code is a very simple REST API that exposes one endpoint but you can easily add more.
But if you're building a RESTful API from scratch then you can consider using some other frameworks like: Hapi, Restify, LoopBack, and other frameworks listed on http://nodeframework.com/ - Express is a very solid but fairly minimal framework and it's not the only option out there.
Yes you can. express is capable to return response other that html element.
However, I would recommend you to use swagger project in developing REST API via express. The project will surely come in handy when developing and MAINTAINING API, especially if your API is huge and complex (lots of url and operation).
This site has a good explanation on how to install, use and run the swagger in NodeJs.
You can do this with express - see below
Install express and body-parser, feel free to use the module below
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
module.exports = {
init: function(module_Enabled){
var portnum = 1234; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var allowCrossDomain = function(req,÷ res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
}
};
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(allowCrossDomain);
var server = app.listen(portnum, function() {
var host = server.address().address;
var port = server.address().port;
console.log("Content Provider Service listening at http://%s:%s", host, port);
});
app.get('/', function(req, res) {
res.send('data');
});
}
}
Related
General information about my setup
Currently I am building a web application using react and a nodejs API that is providing the data for this web application. Both apps are hosted on heroku.com and run independently from each other. I have bought a custom domain from a different hosting provider and used the heroku custom domain option to point the DNS to my website.
Technical details about my setup
NodeJS server: Express
NodeJS version: v10.15.0
React version: v16.2.0
Custom domain: www.tabbs.nl
Heroku domain: tabbs-web-app.herokuapp.com
The issue I am experiencing
I have been digging into a lot of documentation and tutorials in order to setup SSL for react / NodeJS but couldn't find a decent tutorial about how to set SSL / security for my setup.
Tutorials I already have read:
Node + Express + Lets Encrypt
How to use SSL/TLS with nodejs
Stack overflow posts and probably a whole lot more I am forgetting right now.
What do I want to achieve?
The goal I would like to achieve is setting up a secure connection between React web application (frontend) and NodeJS API (backend) so that all data between those is encrypted and safe. Also I want my custom domain (bought by a different hosting provider than Heroku) to be secure and forced using https.
For any questions or additional information please do not hesitate to ask!
Have you tried using the https module in node?
You can do something like this:
var express = require('express');
var https = require('https');
var http = require('http');
var app = express();
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests. This makes it easy to provide both HTTP and HTTPS versions of your app with the same code base, as the app does not inherit from these (it is simply a callback.
If you are using create react app, open your terminal and type “npm run build”. This creates a build folder with all of your static files.
Now go back to your node backend service and add the following:
var express = require('express');
var path = require('path');
var https = require('https');
var http = require('http');
var app = express();
const options = {
key: fs.readFileSync("/srv/www/keys/my-site-key.pem"),
cert: fs.readFileSync("/srv/www/keys/chain.pem")
};
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
If you’re using react router to handle routing for you web app then you would amend the GET request as such:
var express = require('express');
const path = require('path');
var https = require('https');
var http = require('http');
var app = express();
const options = {
key: fs.readFileSync("/srv/www/keys/my-site-key.pem"),
cert: fs.readFileSync("/srv/www/keys/chain.pem")
};
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
This ain't a complex issue, do not worry about ssl, just create your own certificate for Node.JS/Express and that's enough.
and, React has a built-in way of doing api calls,
add this line to package.json of your React installation,
"proxy": "http://localhost:8000/"
and just call the api service like this,
//Generic API Call
callApi = async () => {
const response = await fetch('/api/hello');
const body = await response.json();
if (response.status !== 200) throw Error(body.message);
return body;
};
// A Submit handler to proxy
handleSubmit = async e => {
e.preventDefault();
const response = await fetch('/api/myrequest', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ post: this.state.post }),
});
const body = await response.text();
this.setState({ responseToPost: body });
};
it all works.
I am a newbie in node.js, but I have a sample application written for node.js that shows the way of integration with specific Identity Provider (SAML). Using this sample app I am trying to inspect what is sent in the HTTP requests made from the node.js backend to the remote IdP. Logging the request headers and body by writing to the console.log would be enough for me. Monitoring the network traffic with some tool like Fiddler is not an option for me, because I cannot run it locally, I need to have the app exposed and I have it deployed to Heroku.
I've tried morgan, but it only intercepts the INCOMING requests. I've also tried global-request-logger, but for some reason it does not inject itself into the express framework and passport. Seems like passport is not using the standard modules for HTTP requests?
The question is: what I need to use to be able to log the content of the HTTP requests made by passport during the .authenticate() call? Is there any flag that I am able to set in passport to enable HTTP logging? Or should I rather do it in express? Or maybe some other package would provide the functionality I need?
EDIT:
My original question was marked as possible duplicate of how to log OUTGOING https requests from node within webstorm
But actually I have already seen that topic and I've tried to setup a hook to http module, it was done this way:
'use strict';
// Setup express.js application:
var express = require('express');
var app = express();
// Patch "http" module with outgoing request logging:
var http = require('http');
const originalRequest = http.request;
http.request = function wrapMethodRequest(req) {
console.log('EXTERNAL OUTGOING REQUEST LOGGING:');
console.log(req.host, req.body);
return originalRequest.apply(this, arguments);
}
This approach was not working. As already said in the original question, it seems that passport does not use standard http module? Or did I something wrong with the code above?
As already mentioned in the original question, I was also trying to handle it via global-request-logger package (which as explained in the possible duplicated post, uses the same technique). The code for that was:
'use strict';
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var passport = require('passport');
var SamlStrategy = require('passport-saml').Strategy;
app.use(bodyParser.urlencoded({ extended: false }));
var globalLog = require('global-request-logger');
globalLog.initialize();
globalLog.on('success', (req, res) => {
console.log('HTTP(S) CALLOUT SUCCESS');
console.log('REQUEST: ', req);
console.log('RESPONSE: ', res);
});
globalLog.on('error', (req, res) => {
console.log('HTTP(S) CALLOUT ERROR');
console.log('REQUEST: ', req);
console.log('RESPONSE: ', res);
});
...
I have a NodeJS app I am using as a game server.
I am trying to setup CORS with it, but app.use doesn't seem to be getting called.
Anyone know why?
var util = require("util"); // Utility resources (logging, object inspection, etc)
var fs = require('fs');
var express = require("express");
var app = express();
var port = 3000;
app.use(function (req, res, next) {
// these never get printed out:
util.log( "app.use adding Access-Control-Allow-Origin" );
console.log( "app.use adding Access-Control-Allow-Origin" );
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
var server = app.listen(port, function(){
console.log('CORS-enabled web server listening on port ' + port);
});
var io = require('socket.io').listen(server);
Checkout the npm cors package. https://www.npmjs.com/package/cors
Example usage where all requests will be CORS enabled:
var express = require('express')
, cors = require('cors')
, app = express();
app.use(cors());
app.get('/my_API_URL/:id', function(req, res, next){
res.json({msg: 'This is CORS-enabled for all origins!'});
});
app.listen(80, function(){
console.log('CORS-enabled web server listening on port 80');
});
On their page they also got other examples where the CORS are only enabled on a single route.
Also, just wondering how are you testing your application? You haven't defined any routes in the example code.
As pointed out in the comment section, #Nitzan Wilnai is not doing REST API, apologise for the confusion. It is suppose to be a simple server that listens on a certain port, so for this case you might not need express at all. Did some research and this solution came out;
io.configure('development', function(){
io.set('origins', '*:*');
}
OR
io.set( 'origins', '*domain.com*:*' );
References:
Socket.io doesn't set CORS header(s)
Just in case you are trying to build a chat program. Here is an example project;
https://github.com/socketio/socket.io
I'm developing part of a system where we have two applications sharing the same domain so nginx makes exampleurl.com go to one application and example.com/admin/* go to the second.
The /admin/* part is going to a NodeJs app using express.
Is there an elegant way of making sure that node can add in the /admin without having to do
app.get('/admin/endpoint', ...)
?
you can use http://expressjs.com/fr/api.html#router
var router = express.Router();
router.get('/', function(req, res) {
res.send('One page in admin website');
});
// router.get('/adminWebsite'); // idem for all routes(you always use this router)
app.use('/admin', router);
you would would to use routers (preferably) but you can also create another express app. using different Apps allow you to have more global middlewear control whereas using different routes mean that they share the same express instance.
var express = require('express');
var admin = express(); // <- this is now your admin application
var app = express(); // <- this is your main applicaiton regular users
//you will need to set up middlewear like body-parser and stuff for both of them now
//but it allows you to use different logging and authentication system or w.e you
//want
//once everything is done you can 'MOUNT' virtually the admin app to the regular app
app.use('/admin', admin); //<- this will nest apps together but allow the sub-app admin
//to be it's own instance.
//app.js
const admin = require('admin'); //you admin module (where you routes wiil be)
app.use('/admin', [functions... example authCheck], admin);
//index file of admin module
`var express = require('express');
var router = express.Router();
router.use(function authCheck(req, res, next) {
//check if user is logged
});
router.get('/main', require('./main').get);
module.exports = router;`
//main.js
`exports.get = function(req, res, next){
res.render('admin/admin', {
title: "Main panel"
});
};`
and now you can access site.com/admin/main
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')
);