Node JS serving html file with css - html

I'm practicing pure node js and i've encountred a thing that disturb about http protocole.
I finally served my html page with css after an hour or so of searching and testing my code. Here is my code :
const server = http.createServer((req, res)=>{
if(req.url === "/"){
fs.readFile("index.html", "UTF-8", function(err, data){
res.writeHead(200, {"Content-Type": "text/html"});
res.end(data);
});
}else if(req.url === "/styles.css")){
var cssPath = path.join(__dirname, 'public', req.url);
var fileStream = fs.createReadStream(cssPath, "UTF-8");
res.writeHead(200, {"Content-Type": "text/css"});
fileStream.pipe(res);
};
});
But I didn't understand why it works. Well I've only typed "/" in the browser, I didn't type "/styles.css". And why I don't see "/styles.css" in the URL bar.
I'm sure it's because of how the http protocole is designed but can you help with some explanation of this protocole.
Thank you in advance.

If you had typed /styles.css in the address bar, then you would see the source code the CSS file. For example: this link.
You type /, then the browser asks the server to / and the server responds with an HTML document.
Then the browser renders the HTML document. The HTML document, I assume, includes something like:
<link rel=stylesheet href=/styles.css>
So the browser asks the server for /styles.css and the server responds with a CSS file. The browser then applies that CSS to the HTML document.
It doesn't show /styles.css in the address bar because you are looking at /. The CSS file is just a different resource that is needed to fully render the HTML document that / represents.

Related

Is there any way to serve HTML files in a Node-Express app after basic authentication?

I already have the basic authentication block done.`
app.post("/auth", function (request, response) {
// Capture the input fields
let username = request.body.username;
let password = request.body.password;
// Code checking if user/password are correct. This is working already.
});
I would like to be able to see some HTML pages after that validation is done. Eventually if the users try to access the HTML pages without the proper validation, they should be redirected to the login.html
response.redirect("/login.html");
I'm currently serving the HTML files like this
app.get("/", function (request, response) {
// Render login template
response.sendFile(path.join(__dirname + "/login.html"));
});
but this is exposing the content without the proper validation.

nodejs sendfile html page

I have this code that allows me to open a HTML page from specific folder, if I use server.js to open that HTMLpage so the page it is generating with all the css and jquery files but if I try to move the get statement to the routes folder then the page is generated but without any css and jquery files and I don't know why !
what I did in the server.js for the generation of the HTML page is below which is working perfectly :
const folderPath = __dirname + '/public/AppTemplate/src'
app.use(express.static(folderPath))
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/public/AppTemplate/src/index.html'));
});
but what I'm trying now is to get the html page from routes.js :
step 1 :
I implemented this statement in server.js
app.use('/users', require('./backend/routes/profile.routes.js'));
step2 :I tried this statement in routes.js with simple modification :D :
router.get('/profile', function (req, res) {
const dirname = __dirname;
console.log(dirname)
const newpath = dirname.length - 14;
const newP = dirname.substring(newpath, dirname.lastIndexOf("/"));
console.log(newP);
res.sendFile(path.join(newP+ '/public/AppTemplate/src/02-ProfilePage.html'));
});
the step 2 is working but I couldn't get all the associated files (jquery css ...) which are located in
/public/AppTemplate/src
the image of the output is below :
hope I mentioned everything,
Best Regards,
It's because of the content in the 02-ProfilePage.html has an incorrect path.
Check the path in the script tags. If there is a slash it means that it's already in the /public/AppTemplate/src which you specified.
For example, /js/file.js will actually point to /public/AppTemplate/src/js/file.js
Perhaps try adding a / in front of your path in the script tag.
Example:
/css/x/y/z/ instead of css/x/y/z
You will have to append a / to all the routes in your script/link tag to be able to successfully load the local resources.
You can use the find and replace functionality in your code editor or IDE to speed up the process if possible.

Server or HTML isn't displaying CSS (but works when opening HTML file)

I've been trying to learn how to set up a node.js server for a simple website for the first time and am encountering some strange behavior. When I open my index.html file from my computer it opens up perfectly with all of the CSS working properly. However I then set up a basic node.js server and when accessing the index.html file through my browser it only loads the html but not the CSS.
I'm extremely new to this so haven't been able to try much, also because the code is extremely simple so can't see what's missing (I tried following this tutorial if that helps). I also found another question that seemed similar on here but it didn't have an answer and didn't really help, I did check that all the files are UTF-8.
The HTML:
<html>
<head>
<title>My Page</title>
<link rel="stylesheet" href="styles.css" type="text/css">
</head>
<body>
<h1>A headline</h1>
</body>
</html>
And the node.js server:
const http = require("http");
const fs = require("fs");
const server = http.createServer((req, res) => {
res.writeHead(200, {"Content-Type": "text/html"});
const myReadStream = fs.createReadStream(__dirname + "/index.html", "utf8");
myReadStream.pipe(res);
});
server.listen(3000, "127.0.0.1");
console.log("Listening to port 3000");
When I include the CSS within <style> tags and directly in index.html it does work, but I've tried putting <link rel="stylesheet" href="styles.css" type="text/css"> between <style> tags and that still doesn't (it would also be weird if that's necessary seeing as it displays perfectly when I simply open the html file). I've also tried removing type=text/css but that didn't seem to change anything. Any help would be much appreciated!
You need to serve the style.css as well. You are serving the index.html but in the index.html it is hitting http://127.0.0.1:300/style.css when the request is coming to your app it is STILL serving the index.html file. (You can confirm this in Network pane of developer tools)
const server = http.createServer(function (req, res) {
const url = req.url;
if (url === '/style.css') {
res.writeHead(200, { 'Content-Type': 'text/css' }); // http header
fs.createReadStream(__dirname + "/style.css", "utf8").pipe(res);
} else {
res.writeHead(200, { 'Content-Type': 'text/html' }); // http header
fs.createReadStream(__dirname + "/index.html", "utf8").pipe(res);
}
})
Note: It is very easy to achieve this using express, probably the most popular nodejs package.

Call ExpressJS as Rest API for HTML page

I am creating web page with a button to load data from the server using Rest API build through ExpressJS, NodeJs.
var express=require('express');
var mysql=require('mysql');
var app=express();
var server=app.listen(3000,function(){
console.log("Express is running on port 3000");
});
app.get('/search',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.end(JSON.stringify(data));
});
});
HTML page for this application looks like below
<button >Load from server</button>
<div></div>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('click','button', function(){
$.ajax({
url: "http://localhost:3000/search"
}).done(function() {
$('div').append("done !!! - ");
});
});
});
</script>
When I run http://localhost:3000/search in browser it gives me output with "name" from the database. But how can I see the index.html page and make it load on button click.
Update:
OP Asks:
"my question is not what code say....my question is how to change the
code so that expressjs works as RESTful API and not rendering engine"
In order to use express as a RESTful API here, you first need to serve up a static page.
Said another way, here are the steps:
1. Get your express server to serve up a static page.
2. Then get the button on that page to make a GET request to your api endpoint at /search (when clicked).
1 is explained in the 2nd part of my answer.
2 should already work, you just need to serve the page and click the button!
I explain why this doesn't work in the first part of my answer. You can't simply navigate to /search. I think that is what you mean by "not use it as a render engine".
Original Answer:
To understand what is happening here, it might be a good idea to look at how you're handling requests in your serverside code:
When I run http://localhost:3000/search in browser it gives me output with "name" from the database.
That code is:
app.get('/search',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.end(JSON.stringify(data));
});
});
This means that whenever a GET request goes to your route (in this case, the path /search on localhost:3000), the callback function executes. Essentially, when you access localhost:3000/search, your browser sends a GET request, Express checks* the request for a match with each route, and finally going "ok, that's the GET request I need to respond to, let's start searching!".
So it's behaving as expected. Of course, that is not what you want...
But how can I see the index.html page and make it load on button click
Try something like this:
app.get('/', function(req,res) {
res.sendfile('public/index.html');
});
It might not work as is, depending on where your html is defined and what you've named it. Remember to send the right file.
A simpler way to reason about this would be to let express know you're serving up static html.**
That could be done with
app.use("/", express.static(__dirname)); But again, make sure the html defined above is in a file in the proper root folder (probably named server or something similar), with the name index.html (and that there is only one of them).
(See the links on how express middleware works, and serving static HTML, at the bottom)
To wrap up, you implement the second half this answer first, so that you can go directly to localhost:3000 to load your index page. That page will have a button. Then, you'll be able to click the button and make a request to your /search route, without redirecting. The contents of name should come back to the browser now (instead of being served as a new page).
*More on how requests get checked/processed here.
**More info on serving static html. This blog on express fundamentals may also be useful.
1-You have to add routing for index.html
app.get("/index", function(req, res) {
res.render(index.html);
});
And then in your ajax code you can redirect to /index using window.location
2- you can directly render index.html.
Something like this
app.get("/search", function(req, res) {
res.render(search.html,{});
});
app.get('/index',function(req,res){
var mysql=require('mysql');
var connection = mysql.createConnection({
connectionLimit : 100, //important
host : 'localhost',
user : 'root',
password : '',
database : 'node-test'
});
connection.connect();
connection.query('SELECT name from users', function(err, rows, fields) {
if (err) throw err;
var data=[];
for(i=0;i<rows.length;i++){
data.push(rows[i].name);
}
res.render(index.html,{data:data});
});
});
then redirect to page on /index when clicking button.
The problem you have is that you are using Express as a render FrameWork. If you want to build an app with REST/API, the framework should not render the views or templates. The webpage navigation should be separate (e.g Angular JS). In your case, when you call /search you are actually only calling something in the server without any rendering instruction. That is why you see a response JSON object instead of your html template.
So, what to do?.. You need to make a navigation app on your client side, just navigating through templates with nothing out of normal, and program your button to do its request to some api url (something like: localhost:3000/api/search) and with the contents of the response do something: like filling a table, showing them somehow or whatever..
I recommend you to give a try to Angular JS. I am sure it can help you
Cheers
Here is the code I use when I am wanting to use a simple index.html page for test some front-end code.
app.get("/", function(req, res) {
res.sendFile( __dirname + '/index.html')
});
This will map the root path to your index.html. The __dirname assumes the index.html file is in the same directory as your initial server/app file for express. If you want to make it more generic you can do something like the following but then you will need to manually add the index.html to the address bar in your browser but it also lets you load any other static files you want.
app.get(/^(.+)$/, function(req, res){
res.sendFile( __dirname + req.params[0]);
});
<button >Load from server</button>
<div></div>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('click','button', function(){
$.ajax({
url: "http://localhost:3000/search"
}).done(function(data) {
$('div').append(data);
});
});
});
</script>
you can read the documentation about $.ajax() from jquery api documentation
http://api.jquery.com/jQuery.ajax/

node.js code to open a page in browser with localhost URL

I have written a simple server using node.js. At the moment the server responds by writing "hello world" to the browser.
The server.js file looks like this:
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8080);
I use this URL in the browser to trigger the "hello world" response:
http://localhost:8080/
I want to be able to open a basic html page when I pass a URL like this:
http://localhost:8080/test.html
I have looked through many tutorials and some stackoverflow posts but there was not much out there on this specific task. Does anyone know how to achieve this with a simple modification to the server.js file?
If you wish to open .html file through nodejs with the help of "http://localhost:8080/test.html" such url, you need to convert .html page to .jade format.Use rendering engine with the help of expressjs framework.Express rendering engine will help you to render .jade file on nodejs server.
It is better to use a front end javascript frameworks such as Angular, React or Vue to route to different pages. Though, if you want to do it in Node, you could do something like this using express:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sendFile('views/index.html', { root: __dirname })
});
app.get('/test', function(req, res) {
res.sendFile('views/test.html', { root: __dirname })
});
app.listen(8080);
This is an ok solution for static pages. Express is very useful for writing REST API's.