Can someone explain why this code is working? - node.js

So i am using marked (a markdown module) with express, i am not setting the title var or rendering anything and yet the title var is being mutated -i guess- here is the code to my index.js route :
/*
* GET home page.
*/
exports.index = function(req, res, marked){
marked('Why is this even __working__?.');
};
and here is the code to my index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
</html>
and here is what i am getting in the browser, although i restarted the app so many times!!:

You have misunderstood the connect/express middleware function signature. You have:
exports.index = function(req, res, marked){
But that's not right. It's req, res, next and there's no marked involved. So you aren't rendering markdown, you're passing a string to next() which connect/express treat as an error. Your code does this once you remove the misnamed function parameter confusion:
exports.index = function(req, res, next){
next('Why is this even __working__?.');
}
So connect sees next was passed an error string and express render's the default error page with that as the error message.

Related

Why res.send( string ) download a file

I have an app where I want to render static html with express.
I know about res.sendFile() but that is not what I want to use. I want to load my files using fs and send them using res.send()
I do something like this :
fileFoo = fs.readFileSync('./html/foo.html', 'utf-8');
fileBar = fs.readFileSync('./html/bar.html', 'utf-8');
app = express()
app.get('/foo', (req, res) => res.send(fileFoo));
app.get('/foo/bar', (req, res) => res.send(fileBar));
With 2 very simple html files
foo.html
<html>
<head>
<title>FOO</title>
</head>
<body>
<h1>FOO</h1>
bar
</body>
</html>
bar.html
<html>
<head>
<title>BAR</title>
</head>
<body>
<h1>BAR</h1>
</body>
</html>
When I go to /foo I got a HTML rendered.
If I click on bar I do not get a new HTML page rendered but I got a file "bar" with no extension downloaded. The file of course content the HTML page.
What is happening ?
UPDATE :
I am actually using a router, not direct app.
And I think this 'download' occure only when I try to reach
router.get('/', (res, req) => res.send(fileBar));

Send html page to client

I form the markup of the html page and write to the variable htmlToSend
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hyperspotters</title>
</head>
<body style="margin: 0;
font-family: Arial, Helvetica, sans-serif;">
<header>
<div style="background: #3366CD; padding: 10px">
....
I need to return it to the client.
I promoted so
let htmlToSend = func.statusСheck(success, replacements);
return res.sendFile(htmlToSend);
and
let htmlToSend = func.statusСheck(success, replacements);
return res.render(htmlToSend);
How do I get my markup back to the client?
Normally, the middleware functions of Express.js expose the req and the res objects, with the res beeing the response object, which you use to send responses back to a client.
Example:
app.use(function (req, res, next) {
});
As stated by #jacob already, use the send function of the response object to send a reply to the client. You should, however, send the data as string (not buffer), because using a buffer leads to the data beeing interpreted as binary data, but clearly you are sending text. Also, using a buffer makes express set a Content-Type of 'application/octet-stream', which is also not what you want. Instead, set it to 'text/html'.
app.use("/", function (req, res, next) {
res.set('Content-Type', 'text/html');
res.send(htmlToSend);
});
See: http://expressjs.com/en/guide/routing.html
And also: https://expressjs.com/en/4x/api.html#res.send
It's not clear what exactly you are trying to achieve.
If you want to render HTML, try this code.
res.render('index', function(err, html) {
res.send(html);
});
where index is the view
If you want to respond with HTML content, try this code.
res.set('Content-Type', 'text/html');
res.send(new Buffer(htmlToSend));
don't forget to set Content-Type.
You can achieve this one of the following ways:
// serve your files as static
// 'public' -- your static files folder, set path accordingly
app.use('/static', express.static(__dirname + 'public'))
Assuming you've index.html in your public folder, you can access file like yourhost:port/static/index.html
Or use template engine through view engine (like ejs, 'pug', nunjucks etc) like:
// assuming you use ejs
const ejs = require('ejs'); // install ejs package
// your views folder (say folder named "views")
app.set('views', __dirname + 'views')
app.set('view engine', 'ejs')
// Assuming you've index.ejs in your views folder
// in your router
...
res.render('index');
More about templating engines and serving static here

Express only serving css file in main page

I am learning node and using expressjs the problem is that the css file is only working on the main page and not any other page following is the code for the app:
var express = require("express");
var app = express();
// assets
app.use(express.static("public"));
// simple file testing
app.get("/anything/:stuff", function(req, res){
var stuff = req.params.stuff;
res.render("love.ejs", {stuff: stuff});
});
// posts page
var books = [
{title:"Harry Potter",author:"JK Rowling",editions:7},
{title:"Peere Kamil",author:"Humaira Saeed",editions:4},
{title:"Mushaf",author:"Abdullah khan",editions:2}
];
app.get("/books", function(req, res){
res.render("books.ejs",{books:books});
});
app.listen(3000, process.env.IP, function(){
console.log("Serving Now!");
});
The following is the code for the page where it is not working.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="app.css" />
<title>demo app</title>
</head>
<body>
<h1>You fell in love with : <%= stuff %> </h1>
<%
if(stuff.toUpperCase() === "WAQAS"){ %>
<P>GOOD CHOICE HE IS THE BEST</p>
<% } %>
<p>P.S This is the love.ejs file</p>
</body>
</html>
The file is under public directory.
Use an absolute URL for the CSS file, so the browser doesn't look for it relative to the current URL:
<link rel="stylesheet" href="/app.css" />
Explanation: say that you open the URL /anything/helloworld in your browser. When your HTML contains just app.css, without the leading slash in front of it, the browser will try and load /anything/app.css (because without that slash it's relative to the current URL), which doesn't point to your CSS file.
When you add the leading slash, express.static will be able to find the CSS file in public/.

Render ejs template with the passed object

For some reason the following object isn't being passed through to the page correctly.
I'm able to console.log with this function, which returns a json object of the signed in user.
app.use(function(req, res, next){
console.log(req.user);
next();
});
However, when I store it as a variable through the route it comes up as undefined. Any idea where the disconnect is?
app.get('/', function(req, res) {
res.render('index.ejs',{
bootstrappedUser: req.user
});
});
The following results in bootstrappedUser in "bootstrappedUser is not defined "
<body ng-app="hcApp">
<script>
console.log(bootstrappedUser);
</script>
Your latest snippet code is rendered by your server but is executed by the client's browser. Thus, your browser does not know what is bootstrappedUser.
But, if you do this:
<body ng-app="hcApp">
<script>
console.log("#{bootstrappedUser}");
</script>
...
The server will render your code to (suppose bootstrapUser is equal to foo):
<body ng-app="hcApp">
<script>
console.log("foo");
</script>
...
Now, the client's browser can executed the code without problem.
EDIT: Sorry, you are using EJS template (not jade). So, to render the variable: <%= bootstrappedUser %>:
<body ng-app="hcApp">
<script>
console.log("<%= bootstrappedUser %>");
</script>
...

Express & EJS - layout.ejs not used

Im trying out EJS as a view engine with Express. It seems that my layout.ejs is not used. I have two views index.ejs and layout.ejs both in my 'views' folder. It seems that index.js is rendered but layout.ejs is not. The layout.ejs file should be including a CSS file but when the page is rendered in the browser this is not there. Any test test text that I place in the layout.ejs file is not output with the response.
Am I missing an additional configuration step?
Thanks!
My server.js code:
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('index.ejs', {title: 'EJS Engine'});
});
app.listen(8080);
In my layout.ejs I am linking to a single css file which resides in the public folder.
layout.ejs:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<%- body %>
</body>
</html>
index.ejs
<div id="container">
index.html
</div>
Here's the module you need:
https://www.npmjs.org/package/express-ejs-layouts
Do the following:
npm install express-ejs-layouts // install the layout module from the command line
var express = require("express")
,path = require('path')
,fs = require('fs')
,expressLayouts=require("express-ejs-layouts") // add this requirement
, app = express();
app.use(express.bodyParser());
app.use(expressLayouts); // add this use()
app.use(express.static(__dirname));
Now the ejs engine should use your layout.
app.set('view options', { layout:'layout.ejs' });
Place layout.ejs into your views folder.
Alternately you can place layout.ejs into views/layouts folder and then use
app.set('view options', { layout:'layouts/layout.ejs' });
I have a similar issue. In my case I would rather use Jade but I have a requirement for a more "html" style template engine for a particular project. At first I considered express-partials or ejs-locals (as mentioned in a comment by Jonathan Lonowski) or even using html via the pipe or dot syntax within Jade templates (see here for more information about that option and this SO post). I am not able to introduce the additional dependencies for express-partials and ejs-locals into this project. These two projects do look good and might meet your needs.
If you do not want to use these projects, you can do something like the following:
views/layout-head.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The title</title>
</head>
<body>
views/layout-foot.ejs
</body>
</html>
views/index.ejs (or any other page)
<% include layout-head %>
This is the index page - <%= title %>
<% include layout-foot %>
routes/index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
}
This is not an optimal solution but it works. Most of my application will be a single page app and I have some other restrictions I have to work within so this works for my needs. This may not the best solution in many cases - especially if you have complex and/or changing layouts.

Resources