Simple node.js server that sends html+css as response - javascript

I've created basic http server that sends html file as response. How can I send css file as well so client using browser will see a html using css ?
The code I have:
var http = require('http');
var fs = require('fs');
var htmlFile;
fs.readFile('./AppClient.html', function(err, data) {
if (err){
throw err;
}
htmlFile = data;
});
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
response.end(htmlFile);
});
//Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");
What I have tried(it seems it does not work - client sees only css file content here):
var http = require('http');
var fs = require('fs');
var htmlFile;
var cssFile;
fs.readFile('./AppClient.html', function(err, data) {
if (err){
throw err;
}
htmlFile = data;
});
fs.readFile('./AppClientStyle.css', function(err, data) {
if (err){
throw err;
}
cssFile = data;
});
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/css"});
response.write(cssFile);
response.end();
response.writeHead(200, {"Content-Type": "text/html"});
response.write(htmlFile);
response.end();
});
//Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");
html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="AppClientStyle.css">
</head>
<body>
<div class=middleScreen>
<p id="p1">Random text</p>
</div>
</body>
</html>
css file :
#CHARSET "UTF-8";
.middleScreen{
text-align:center;
margin-top:10%;
}
I don't want to use express here(it is just for learning purpose)

What you have written in your first snippet is a web server that responds with the body of your HTML file regardless of what URI the browser requests.
That's all nice and well, but then with the second snippet, you're trying to send a second document to a closed response handle. To understand why this doesn't work, you have to understand how HTTP works. HTTP is (for the most part) a request->response type protocol. That is, the browser asks for something and the server sends that thing, or an error message of some sort, back to the browser. (I'll skip over keep-alive and methods that allow the server to push content to the browser--those are all far beyond the simple learning purpose you seem to have in mind here.) Suffice it to say that it is inappropriate to send a second response to the browser when it hasn't asked for it.
So how do you get the browser to ask for a second document? Well, that's easy enough... in your HTML file you probably have a <link rel="stylesheet" href="AppClientStyle.css"> tag. This will cause the browser to make a request to your server asking it for AppClientStyle.css. You can handle this by adding a switch or if to your createServer code to perform a different action based on the URL the browser requests.
var server = http.createServer(function (request, response) {
switch (request.url) {
case "/AppClientStyle.css" :
response.writeHead(200, {"Content-Type": "text/css"});
response.write(cssFile);
break;
default :
response.writeHead(200, {"Content-Type": "text/html"});
response.write(htmlFile);
});
response.end();
}
So, first, when you access your server at http://localhost:8000 you will be sent your html file. Then the contents of that file will trigger the browser to ask for http://localhost:8000/AppClientStyle.css
Note that you can make your server far more flexible by serving any file that exists in your project directory:
var server = http.createServer(function (request, response) {
fs.readFile('./' + request.url, function(err, data) {
if (!err) {
var dotoffset = request.url.lastIndexOf('.');
var mimetype = dotoffset == -1
? 'text/plain'
: {
'.html' : 'text/html',
'.ico' : 'image/x-icon',
'.jpg' : 'image/jpeg',
'.png' : 'image/png',
'.gif' : 'image/gif',
'.css' : 'text/css',
'.js' : 'text/javascript'
}[ request.url.substr(dotoffset) ];
response.setHeader('Content-type' , mimetype);
response.end(data);
console.log( request.url, mimetype );
} else {
console.log ('file not found: ' + request.url);
response.writeHead(404, "Not Found");
response.end();
}
});
})
Start this in the same directory as your HTML and CSS files. The above is simplistic, error-prone and INSECURE. But it should be sufficient for your own learning or local development purposes.
Keep in mind that all the above is far less succinct than just using Express. In fact, I'm not sure why you wouldn't want to use Express, so I'm going to try to convince you to try it:
$ npm install express
$ mkdir www
$ mv AppClientStyle.css www/
$ mv AppClient.html www/index.html
Your script will look like: (Borrowed from Express Hello World)
var express = require('express')
var app = express()
app.use(express.static('www'));
var server = app.listen(8000, function () {
var host = server.address().address
var port = server.address().port
console.log('Express app listening at http://%s:%s', host, port)
})
Then run your script and point your browser to http://localhost:8000. It really is that painless.

Integrate the CSS right into your AppClient.html file. There are different ways to do so:
External CSS file
Create a styles.css file (or any other file name) in the same directory as your html file. Then add
<link rel="stylesheet" type="text/css" href="styles.css">
to your <head> section of your HTML document.
OR
Right in your HTML file
Add a
<style>
YOUR STYLES RIGHT HERE
</style>
to your <head> section of your HTML document.

Related

Client Recieves Data From Server

So I have a Raspberry Pi 4 and im trying to receive data from a JSON file and display it on a text element on my website. sorry if im totally wrong, it's my second day with a Raspberry Pi. I have done basic things like turn an LED on, thanks to w3schools. Im trying to make a bot hosting tool thing for myself, where it will display amount hosted on a TV
index.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="index.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
</head>
<body>
<div class="container">
<h1>Bots Hosted:</h1>
<h2 id="bot-qty">0</h2>
</div>
</body>
<script>
var socket = io();
window.addEventListener("load", function() {
var bot_count = document.getElementById("bot-qty");
var times_ran = 0;
const interval = setInterval(function() {
socket.emit("request-count", times_ran);
times_ran++;
}, 20000);
})
socket.on('request-count', function(data) {
document.getElementById("bot-qty").innerText = data;
})
</script>
</html>
webserver.js:
var http = require('http').createServer(handler);
var fs = require('fs');
var io = require('socket.io')(http);
http.listen(1337);
function handler(req, res) {
fs.readFile(__dirname + '/public/index.html', function(err, data) {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
return res.end("404 Not Found");
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
return res.end();
});
}
io.sockets.on('connection', function(socket) {
socket.on('request-count', function(data) {
var bot_count = JSON.parse(fs.readFileSync("config.json", "utf8"));
console.log(bot_count);
socket.emit('request-count', bot_count);
});
});
In console, it says
GET <long_url_here> net::ERR_NAME_NOT_RESOLVER
In the index.html you initialize a new Socket instance by writing
var socket = io();
You don't provide any url, so the socket.io-client will use the default window.location as can be seen here. This might be a problem, so try to set a specific url, e. g.
var socket = io('http://localhost');
or (also specifying the port)
var socket = io('http://localhost:1337');
Also try to make sure that you run your webserver.js with node webserver.js prior to open the website.
Also see this discussion on GitHub.

Style and javascript files not applied to page that is serving HTML in Node.js

I am currently serving my HTML page which references style.css and index.js, however, these files are not being applied to the HTML page even though I explicitly stated to include them if they are requested by 'req'?
My HTML (to show inclusions):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test site</title>
<link rel="stylesheet" href="/style.css" media="screen">
<script src="/index.js" charset="utf-8" defer></script>
.
.
.
My server.js code:
var PORT = 3000;
var http = require('http');
var fs = require('fs');
var path = require('path');
//cache the files
var index = fs.readFileSync('public/index.html', 'utf8', function read(err, data) {
if (err) {
throw err;
}
});
var style = fs.readFileSync('public/style.css', 'utf8', function read(err, data) {
if (err) {
throw err;
}
});
var indexJS = fs.readFileSync('public/index.js', 'utf8', function read(err, data) {
if (err) {
throw err;
}
});
function requestHandler(req, res){
res.setHeader('Content-Type', 'text/html');
res.statusCode = 200
res.write(index);
if(req.url === '/style.css'){
res.write(style);
}
if(req.url === '/index.js'){
res.write(indexJS);
}
res.end();
}
//use 3000 by default if PORT is not defined
if(!(typeof PORT !== 'undefined') || PORT === null){
http.createServer(requestHandler).listen(PORT);
}
else{
http.createServer(requestHandler).listen(3000);
}
Looks like you have the right idea but there are a couple things to note in the server code.
Setting the Content Type header tells the web browser how to interpret the file it is receiving. Your server code always sets it to 'text/html' where it should be set to 'text/css' for css, and 'text/javascript' for your js files.
res.write will append the file contents to the response. Since res.write(index) is being executed on every request, your HTML is being sent before the css/js within the same file. Try using a conditional for HTML like you are doing for CSS/JS like
if(req.url === '/') {
res.setHeader('Content-Type', 'text/html');
res.write(index);
}

Webcam doesn't display when node.js it's running

I have a script that takes a picture from my webcam.
it's working fine when i runs locally or when i see in a online server.
But when i run the html file from the node.js, it doesnt show the view from my webcam.
how to fix that?
MY SERVER IN NODE:
// app.js
var http = require('http');
var fs = require('fs');
sys = require('util');
var server = http.createServer(function(request, response){
fs.readFile(__dirname + '/index.html', function(err, html){
console.log("oi");
response.writeHeader(200, {'Content-Type': 'text/html'});
response.write(html);
response.end();
});
});
server.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
MY HTML:
<!DOCTYPE html>
<html>
<head>
<title>Javascript Webcam Demo - <MyCodingTricks/></title>
</head>
<body>
<h3>Demonstrates simple 320x240 capture & display</h3>
<div id="my_camera"></div>
<!-- A button for taking snaps -->
<form>
<input type=button class="btn btn-success" value="Take Snapshot" onClick="take_snapshot()">
</form>
<div id="results" class="well">Your captured image will appear here...</div>
<!-- First, include the Webcam.js JavaScript Library -->
<script type="text/javascript" src="2/webcam.min.js"></script>
<!-- Configure a few settings and attach camera -->
<script language="JavaScript">
Webcam.set({
width: 320,
height: 240,
image_format: 'jpeg',
jpeg_quality: 90
});
Webcam.attach( '#my_camera' );
function take_snapshot() {
// take snapshot and get image data
Webcam.snap( function(data_uri) {
// display results in page
document.getElementById('results').innerHTML =
'<h2>Here is your image:</h2>' +
'<img src="'+data_uri+'"/>';
Webcam.upload( data_uri, 'upload.php', function(code, text) {
// Upload complete!
// 'code' will be the HTTP response code from the server, e.g. 200
// 'text' will be the raw response content
});
} );
}
</script>
</body>
</html>
Your program seems to be sending the content of index.html for every request (for html, icons, scripts, etc.). Maybe try using express to serve static files properly:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname));
app.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
It's even easier than the way you want to write it, because to make your script work you would have to manually route the requests based on the request object to properly send scripts and different assets, make sure to handle MIME types, paths like ../.. etc.
Also you may want to move your static files (html, css, js) to a different directory like static and change the app.js like this:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname + '/static'));
app.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
so that no one will be able to get your app.js code by browsing to: http://localhost:3000/app.js

Read css/js files with nodejs and express

I'm a real noob when it comes to nodejs, jsut started this a couple of days ago. I can't figure out why my js and css files aren't applied. There are no 404 errors so that doesn't seem to be it. I'm trying to read the files using express. I'm getting these console errors in dev tools:
GamblerScript.js:1 Uncaught SyntaxError: Unexpected token <
jquery-2.2.0.min.js:1 Uncaught SyntaxError: Unexpected token <
localhost/:5 Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/css/Stylesheet.css".
(index):9 Uncaught ReferenceError: Run is not defined
Is there any one who can see what i'm doing wrong?
var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sendfile('/index.html');
});
app.use(express.static(__dirname + '/public'));
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8080);
});
<html lang="en">
<head>
<title>Dices</title>
<link rel="stylesheet" href="/css/Stylesheet.css">
<script src="/js/GamblerScript.js"></script>
<script src="/js/jquery-2.2.0.min.js"></script>
</head>
<body onload="Run();">
<div id="spinboxcontainer">
<div class="spinbox">
<span class="spinspan">Dices</span>
</div>
<div id="container">
<div id="spinner1" class="spinner">
<div id="D1.1" class="one">1</div>
<div id="D1.2" class="two">2</div>
<div id="D1.3" class="three">3</div>
<div id="D1.4" class="four">4</div>
<div id="D1.5" class="five">5</div>
<div id="D1.6" class="six">6</div>
</div>
</div>
<div id=container2>
<div id="spinner2" class="spinner">
<div id="D2.1" class="one">6</div>
<div id="D2.2" class="two">5</div>
<div id="D2.3" class="three">4</div>
<div id="D2.4" class="four">3</div>
<div id="D2.5" class="five">2</div>
<div id="D2.6" class="six">1</div>
</div>
</div>
</div>
</body>
</html>
function Run(){
alert('Welcome');
var clickNumber = 1;
document.getElementById('spinner1').addEventListener("click", function(){
alert('Your click is number ' + clickNumber + '!');
document.body.className -= ' WhiteBackground';
clickNumber = clickNumber + 1;
});
document.getElementById('spinner2').addEventListener("click", function(){
alert('Your click is number ' + clickNumber + '!');
document.body.className += ' WhiteBackground';
clickNumber = clickNumber + 1;
});
};
You messing up different approaches. If you use express there is no need to http.createServer and manually read your static files with fs.readFile. For simple static server just simplify your main file like this
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080, function() {console.log('server listening on port 8080...')})
The error you've got is because whenever the browser asks server for script files like jquery and GamblerScript your custom http server sends your index.html file back and browser tryes execute it like javascript.
There are a few things you are doing wrong.
In the bottom half of your code, in the callback passed to fs.readFile(), you create a Node server to handle all requests. The emphasized words are key here: you are creating a server using only Node's built-in features, which you shouldn't need to do when using Express; and the server handles all requests, not just those to your index.html file, as I think you intended. So, when the requests for your CSS and JavaScript come in, you are sending index.html as a response. This won't do.
Luckily, the solution is simpler than the original problem. Just do this:
'use strict';
const path = require('path');
const express = require('express');
const app = express();
// This just lets you set an alternate port with an environment variable,
// if you want.
const PORT = process.env.PORT || 8080;
// Set your static folder before any request handlers.
app.use(express.static(path.resolve(__dirname, 'public')));
// Handles request to root only.
app.get('/', (req, res) => {
// If you needed to modify the status code and content type, you would do so
// using the Express API, like so. However, this isn't necessary here; Express
// handles this automatically.
res.status(200);
res.type('text/html');
// Use sendFile(absPath) rather than sendfile(path), which is deprecated.
res.sendFile(path.resolve(__dirname, 'index.html'));
});
// Call the listen() method on your app rather than using Node's http module.
app.listen(PORT, (err) => {
if (err) throw err;
else console.log(`Listening on port ${PORT}`);
});

Node.js Express | JQuery Nothing happens on client when getting a JSON

I want to receive on an HTML5 website JSON from a PostgreSQL database. So, on the server side I use node-postgres module for DB connection and also express module for communication.
The problem is that in the html i am not seeing any alert when getting the data from the server. The alert isn't even thrown.
this is how my code is so far, for anyone that could help:
serverside
var express = require('express');
var app = express();
app.get('/data', function(req, res){
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/spots";
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
res.send('could not connect to postgres');
}
client.query('SELECT * from spots_json where id=3276', function(err, result) {
if(err) {
res.send('error running query');
}
res.set("Content-Type", 'text/javascript'); // i added this to avoid the "Resource interpreted as Script but transferred with MIME type text/html" message
res.send(JSON.stringify(result.rows[0].json));
client.end();
});
});
});
app.listen(3000);
clientside
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"></meta>
<meta charset="utf-8"></meta>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js" ></script>
<script>
$.get('http://localhost:3000/data?callback=?',{}, function(data){
alert(data.type);
},"json");
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The client is now executed on http://localhost:8888/prueba/prueba.html
Im getting a js with the following Response:
"{\"type\":\"Point\",\"coordinates\":[-2.994783,43.389217]}"
The Response can be seen in the following screenshot:
result.rows[0].json is not an object, it is a string. You don't need to stringify it:
res.send(result.rows[0].json);
Edit:
If you use two servers on different ports you will need to use JSONP. jQuery makes this simple on the client side, but you will need to implement it in your server (example):
if(req.query.callback) {
res.send(req.query.callback + '(' + result.rows[0].json + ');');
} else {
res.send(result.rows[0].json);
}
By the way, you need to return if you encounter an error in one of your callbacks to prevent subsequent code from being executed.
if(err) {
res.end('error message');
return;
// Or shorter: return res.end('error message');
}

Categories

Resources