Skip express js view for API routes - node.js

I have my API and Website in same Express Js Project and needs to use ejs view for the website only. But not for the API to return JSON for API routes.
const app = express();
// For static website
app.use(express.static(path.join(__dirname, "public"), {
extensions : ['html']
}));
// API Routes
const bookRoutes = require("./routes/event.route");
app.use("/v1/books", bookRoutes);
// Website
// Set the view engine for dynamic header, footer on website
const ejs = require('ejs');
app.set('view engine', 'ejs');
API
/v1/books
Website
/index.html
How can I skip the view engine for my API routes and apply to /public folder only or even for selected files?
Error message, when I open /v1/books in Postman
{"message":"Failed to lookup view \"C:\\Users\\admin\\github\\test-app\\public\\v1\\books\" in views directory \"C:\\Users\\admin\\github\\test-app\\views\""}
The JSON was expected for /books API
{
id : 1,
name : 'book name'
}

For starters, routes are matched in the order you declare them. So, if you put this first:
// API Routes
const bookRoutes = require("./routes/event.route");
app.use("/v1/books", bookRoutes);
first, then it will get processed before it tries to match any of the static routes. But, this really shouldn't be an issue because there shouldn't be any files in your public folder that would match a request for /v1/books/xxx anyway.
As for the error for /v1/books, you will have to show us what the code is for bookRoutes. It appears that error is coming from that router. express.static() does not make errors like that.
How can I skip the view engine for my API routes and apply to /public folder only or even for selected files?
The app.set('view engine', 'ejs'); line just configures what view engine will be used if/when some code calls res.render(). There's nothing happening with the view engine on one of your API requests because you should never be calling res.render() in an API route. You are presumably calling res.json() instead.
You should ONLY have files in your public folder that you want express.static() to match. That's how you control it. Don't put something in that folder that shouldn't be served statically.

Related

How to configure Firebase hosting to use pug instead of html file?

I want to hosting my webapp to firebase hosting but it seems that firebase doesn't work with pug template because it return me 404 page not found with my "index.pug".
Thanks in advance.
Firebase Hosting won't compile any sort of frameworks or templates for you. It just serves static content. If you want to use a pug template, you'll have to compile it, then move the static assets into the Firebase Hosting public directory.
tested as of 2020-05-16. express + pug works on firebase hosting.
a few notes :
test with a private window of your browser ;
after you deploy, it may take a couple more seconds for the pug page to be available. i'm from Hongkong while i'm deploying the functions to the default location us-central, not sure if this is related though ;
the view you submit to "res.render", for example, make sure it's index and NOT /index ;
try these :
[project folder root]/functions/index.js
const functions = require('firebase-functions');
const path = require("path");
const express = require("express");
const app = express();
//###############################################################
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
//###############################################################
app.get("/index", function(req, res, next){
res.render("index", {title:"title lo, rendered from index.js"});
});
app.get("/page/:page_num", function(req, res, next){
const page_num = req.params.page_num;
res.render("page", {title:"page here", page_num: page_num});
});
// export to firebase functions
exports.app = functions.https.onRequest(app);
[project folder root]/functions/views/index.pug
h1 okok hello from pug
p this is a line
p another line here
p here is the title : #{title}
[project folder root]/functions/views/page.pug
h1 page
p this is page title : #{title}
p this is page number : #{page_num}
To do that you should use cloud functions. You can use handlebars or pug. Here it is an example using handlebars.
https://github.com/firebase/functions-samples/tree/master/template-handlebars
I haven't used pug, but it should be in the same way that handlebars.
You should divide the dynamic files in the functions folder (pug files goes there under views) and your CSS and JS should be in the public folder. The public only serves static content.
There is a really good video to get a step by step guide (also you can learn about CDN and caching content) here https://www.youtube.com/watch?v=LOeioOKUKI8

Node.js express multitenant app

We are planning a multi tenant app in node.js and express with mongodb. We would have some core functionality exposed via REST APIs. We would have customized functionality for each customer which would process some data and in turn call the REST APIs. The customized functionality as well as the UI(views and public folder) for each customer would reside in a separate folder for each customer under a parent folder. My questions are:
When I add a new customer and create a module for him, I should be able to start using it without having to restart the main module (app.js).
I need to redirect the customer to his UI files based on the urls say example.com/cust1/home would go to the parentfolder/cust1/views and example.com/cust2/home would go to parentfolder/cust2/views.
For the prototypes we have node running behind an apache proxy/reverse proxy and run the custom apps on their own ports. But in production we cant have the apps running on so many individual ports or modify the default.conf each time. For the UI we have tried the dynamic routing of express but that didnt work. We tried doing this in app.js:
var cust1 = require('./cust1/custommodule'); //this needs to be done for each new customer module added;
var app = express();
// view engine setup
var basePath = ''; //works if we hard code it to cust1 or cust2 here;
app.use('/', function(req, res, next){
// basePath = path.dirname(req.originalUrl); //this does not work since the app.set is executed before this is assigned
app.engine('html', require('ejs').__express);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, basePath + '/views'));
next();
});
app.use('/:custom', express.static(__dirname + basePath + '/public'));
app.use('/cust1', cust1); //request coming with /cust1 should use this module, but this again needs to be done for each new customer module added;
Not sure if this is the right way. Any pointers would be appreciated.

expressjs - not sending the file from view config

In my node app, I configured the views folder, later simply I am passing the html name alone. now the html file need to load from using the views config + html file right. ( am I wrong!)
But it's not working. any one give me the suggestion please?
here is my code :
var express = require('express'),
http = require('http'),
jade = require('jade'),
app = express();
app.set('view engine', 'jade');
app.set('views', __dirname + '/views'); // i configured the path so i am passing file name alone on get.
app.get('/', function(req,res){
res.sendfile('index.html'); //it's not working
res.sendfile('views/index.html') //it works
});
http.createServer(app).listen(3000, function () {
console.log('Express server listening on port ');
});
thanks in advance
You appear to have a misconception about what the view engine is. The view engine takes some non-HTML code, and transforms it into HTML. Here, you have it set to use jade.
The view engine is only good with the res.render() function. res.sendfile() merely sends a file from the current directory -- not the views directory.
Using express if you want to serve some static HTML files. You can just put those files directly in public folder.
When server will get a GET request of / it will search for /public/index.html serve that as response. You don't have to add router for that /.
Other wise if you want to use some template views then you have to use some views engine.

Using holder.js on node.js with express web framework does work

I am using node.js with express web framework and with jade template parser.
I am following the bootstrap examples and have problems with holder.js.
I have put holder.js script into static files (public directory), having in app.js the following:
app.use(express.static(path.join(__dirname, 'public')));
I wanted to display some images with following code in jade template:
img(data-src='/holder.js/500x500/auto')
And it does not work. I checked through the browser and I am able to see holder.js file correctly, but adding any parameters is causing that main page is displayed instead.
I am suspecting that static files handler thinks that there is no such file as holder/500x500/auto and redirects to main page. How can I fix that?
Here is a Runnable with Express and Jade with a couple of Holder placeholders: http://runnable.com/U6IlNqsTu-cR6ZT8/holder-js-in-express-using-jade-for-node-js-and-hello-world
The two placeholders use different themes, with one using the auto flag.
server.js:
var express = require('express')
var app = express();
app.set('view engine', 'jade')
app.get('/', function(req, res){
res.render('index')
})
var server = app.listen(80, function(){})
views/index.jade:
doctype html
html
body
script(src='//cdnjs.cloudflare.com/ajax/libs/holder/2.3.1/holder.min.js')
img(data-src='holder.js/200x200/lava/auto')
img(data-src='holder.js/200x200/sky')
Take the leading slash out of the data-src attribute: holder.js/500x500/auto.

Getting Started with express.js, serving a dynamic HTML

I'm writing a single page web application using node.js and express. After going through some online tutorials, I found out this is how express.js serves a client directory with HTML, javascript and css
app.use(express.static(__dirname + '/public'));
This works great except the fact that public directory has to have .html root file which is static. I'd like to know how can I serve a dynamic HTML file with this same approach.
I want to insert some data into the page for example "Hello user_name" at the top. How do I do that for this single file.
I want to only do it once, at the startup, after that my application will make rest API calls and get plain JSON responses which it will then put it in the page.
You cannot use the express static server to serve dynamic files as far as I'm aware. In order to serve a dynamic HTML you need to use a templating engine, such as jade or any of these templating engines.
Jade is pretty straightforward to use and is supported by express by default. To set up jade, include the following lines in your app configuration block:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
The first line sets your views directory - from which the template files would be served. Since you want to serve only an index file, this directory would contain your index.jade template. The second line sets jade as the templating engine.
Now, instead of using the static server to serve the index.html, you need to create a get route '/' to serve the index file, like so:
app.get('/', function(req, res) {
res.render('index', {user_name: username});
});

Resources