Express | Routing is messing up css - node.js

I ran into a problem I couldn't find an answer for.
I'm using Express for my website's framerwork and I'm using its routing but it seems to mess up links and files attached to a page.
Here is what I use :
app.get('/profile/:name/:age', function(req, res) {
var name = req.params.name;
var age = req.params.age;
someFunction(name, age, function(error, profile) {
res.render('userprofile', profile);
});
});
The page renders but the links are broken, instead of going to example.com/css/main.css it goes to example.com/profile/(whatever name I went to)/css/main.css so this returns html instead of the css file. Same things for my links.
Note that I can show up that, with css enabled, no problem :
app.get('/profile', function(req, res) {
res.render('userprofile');
});

Sounds like you're using relative url's for your CSS:
<link rel="stylesheet" href="css/main.css">
If the current (page) url is /profile/username/, that translates to:
/profile/username/css/main.css
Solution? Use absolute url's for resources and links:
<link rel="stylesheet" href="/css/main.css">

Related

How to return a 404 Not found page in an Express App?

I have an express app, in which I have the following code:
app.get('*', (req, res) => {
res.send('404', {
title: 404,
name: 'James Olaleye',
errorMessage: 'Page not found',
});
});
However, My IDE is warning about this message:
express deprecated res.send(status, body): Use
res.status(status).send(body) instead
And with the above code, My Browser is returning the following payload as a JSON object:
{
"title": 404,
"name": "James Olaleye",
"errorMessage": "Page not found"
}
What I want, is to display a 404 Not found page to the user, how can this be achived?
You have two seperate problem
1: you are using an old way to response to the request insted use this res.status(STATUS_CODE).send(BODY)
2: you are sending a json yet you want to display a 404 page in this case you need to send a html template
so your code should look like this
app.get('*', (req, res) => {
res.status(404).send("<div>404 Not Found</div>");
});
I updated your question a bit to make it clearer for future references.
the method res.send is deprecated, among other things because it's usages is too ambiguous. A server response, can be a lot of things, it can be a page, it can be a file, and it can be a simple JSON object (which you have here).
In your case, when you run res.send(404,{ /*...*/ }), the express app assumes you want to send a JSON object, so it does just that.
There are multiple possible ways, to achieve what you want, but I will stick to the most simple solution.
If you want to display an HTML page, in the most simplest form, you can actually just change your piece of code to do this instead:
app.status(404).send(`<h1>Page not found</h1>`)
This will essentially, show a page, instead of a JSON object.
You can even define the whole HTML file if you like:
app.status(404).send(
`
<html>
<!DOCTYPE html>
<head>
<title>404</title>
</head>
<body>
<h1>James Olaleye</h1>
<h1>Page Not Found</h1>
</body>
</html>
`
)
This would be the fastest way to achieve what you want.
A step further, would be to create an HTML file some where in your app, and to send the HTML file instead.
If your source code looks like this:
/
src/
index.js
htmls/
404.html
<!-- htmls/404.html -->
<html>
<!DOCTYPE html>
<head>
<title>404</title>
</head>
<body>
<h1>James Olaleye</h1>
<h1>Page Not Found</h1>
</body>
</html>
// src/index.js
const express = require('express');
const app = express();
const path = require('path');
const PORT = 3000;
app.get('/', function(req, res) {
const options = {
root: path.join(__dirname, '..', 'htmls')
};
res.sendFile('404.html', options, function (err) {
if (err) {
next(err);
} else {
console.log('Sent:', fileName);
}
});
});
This would allow you to have multiple HTML files which you can send around.
There are like I stated, other options as well, but that would make this answer way too long and out of scope. If you are interested, you can research Using template engines with Express and start with the following link.
Happy coding :)

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));

How to serve static files to different routes in Express?

I am creating a site using Express, and when I try to use routes more than one level deep, none of my static files get served. For example, here is my code that is working correctly:
const express = require('express')
const app = express()
const port = 3000
app.use('/public', express.static(__dirname + '/public'))
app.get('/newSite', (req, res) => res.sendFile(__dirname + '/newSite.html') )
app.get('/organizations', (req, res) => res.sendFile(__dirname + '/organizations.html') )
app.listen(port, () => console.log(`listening on port ${port}!`))
I wanted to use something like this for the path:
app.get('/admin/organizations', (req, res) => res.sendFile(__dirname + '/organizations.html') )
I tried messing around with the app.use function because I am thinking that is where my issue is, but I haven't been able to figure it out so far. How do I serve static files to any route?
Edit: Here is the relevant html
<html>
<head>
<link rel="stylesheet" type = "text/css" href = "./public/global.css"/>
<link rel="stylesheet" type = "text/css" href = "./public/organizations.css"/>
</head>
<body>
</body>
<script src = "public/jquery.js"> </script>
<script src = "public/organizations.js"> </script>
</html>
It's got to do with relative path. With express it's safer to use absolute path.
After your route goes one level deep, the html file which is send needs to search one level up to find the static files. (You can confirm: ../public/global.css will actually link static files correctly in your route /admin/organizations)
Simple fix: use absolute path (notice it starts only with /)
<link rel="stylesheet" type = "text/css" href = "/public/global.css"/>

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/.

trying to render two different pages using two different entry points webpack

My webpack is partitioned to produce two outputs...
entry: {
a: './src',
b: './Authentication'
},
devtool: 'source-map',
output: {
path:'/',
filename: 'scripts/[name].js',
publicPath: '/'
},
So one of my html file (login.html) will call...
<script type="text/javascript" src='scripts/a.entry.js'></script>
And the other (index.html) calls...
<script type="text/javascript" src='./scripts/b.js'></script>
Now each of these pages is a different route. Obviously index.html will be the main so in my server I did...
var path = require('path');
...
app.use(express.static(path.resolve('public')));
...
app.get('/', function(req, res){
res.sendFile(path.resolve('public/index.html'));
});
Everything renders find when I test it on local. But now I want to access the second login.html on a different route, I added this...
app.get('/login', function (req, res) {
res.sendFile(path.resolve('public/login.html'));
});
But when I go to localhost:3000/login I get this error...
GET http://localhost:3000/scripts/a.entry.js 404 (Not Found)
The output is not found. Why is this so???
You configured your bundle for login.html to be named “a”, not “a.entry”. Try changing your script tag to:
<script src='scripts/a.js'></script>
(you don't need type="text/javascript" anymore in 2016)

Resources