Internal scripts and style-sheets always points to index file (Node.JS) - linux

This is really weird problem. I just installed Node.JS on my system (Fedora).
I have three files in /var/www/mirror/:
server.js
client.js
index.html
File server.js is the one I call via CLI: node server.js.
It, basically, returns index.html.
var
http = require('http'),
io = require('socket.io'),
fs = require('fs');
http.createServer(function(request, response) {
fs.readFile(__dirname + '/index.html', function(error, data) {
if (error) {
result.writeHead(500);
console.log('Error: Could not read index.html.');
}
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(data);
});
}).listen(1337, '127.0.0.1');
console.log('Server is running.');
All works as expected and no errors are thrown anywhere.
In index.html I have simple HTML5 structure (nothing unnecessary, really!) and <script /> that points to, already mentioned, client.js.
That line of code looks like this (Ctrl + U; from browser):
<script src="client.js"></script>
By moving cursor on client.js, I got actual location: http://127.0.0.1:1337/client.js.
Seems correct, right?
The problem:
By opening that link it opens wanted file, but the content is as server.js should return.
This disallows me from including any internal scripts and style-sheets!
I guess that anything that goes via http://127.0.0.1:1337/ (also http://127.0.0.1:1337/client.js, http://127.0.0.1:1337/a/b/c etc.) is handled via server.js - and server.js returns index.html (see above).
How can I fix it? Thanks in any advice!

Look at the req.url to tell you the url that the user is requesting. From there, you have to have some code decide whether to serve index.html or client.js.
Also, since I'm guessing index.html isn't changing very frequently, you should probably just read it once, and store the buffer in a variable, rather than reading it on every request.
There are some modules that make serving static files a bit easier. Check out filed for a pretty nice standalone static file

Related

How to "run" an HTML webpage without Express, etc

My question can be pretty similar to others, but I already read a lot of answers, but I don't understand completely the details behind them.
I have to create a node.js REST API, but I don't took any lessons before. So i'm currently reading and trying tutorials to learn to create a simple node.js script.
I installed node.js, i created my script (it's just reading an input field), and when i click on a button, it's supposed to write the input in the console.
The tutorial needs only node.js, and use the .createserver. I understand that node.js is server side and can't be interpreted without it.
The tutorial asks to open the .html file in the browser, directly with the path. The html webpage shows up, but... When i'm pressing "ok", here's the errors :
*app.js:1 Uncaught ReferenceError: require is not defined
Access to XMLHttpRequest at 'file:///.../ApplicationAngular/nodeProject/app.html?name=' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
GET file:///.../ApplicationAngular/nodeProject/app.html?name= net::ERR_FAILED*
All the threads on StackOverflow explains that I need a third-party to run the HTML webpage. But on the tutorial, everything is working fine and never mentions the existance of Express, Cheerio, etc..
Here's the samples of code:
app.html
<input type="text" placeholder="Enter your name" id="name"/>
<input type="button" value="OK" onclick="valid()"/>
<div id="message"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="app.js"></script>
<script>
function valid() {
$.get('', { name: $('#name').val() }, function(data) {
$('#message').html(data.message);
}, 'json');
}
</script>
app.js
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer(function (req, res) {
var url_parts = url.parse(req.url, true);
var name = url_parts.query.name;
if(name){
console.log('Nom: ' + name);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(JSON.stringify({message: 'Hello' + name + ' !'}));
} else {
console.log('No name !');
res.writeHead(200, {'Content-Type': 'text/plain'});
fs.readFile('app.html', function (err,data)
{
res.end(data);
});
}
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Is the tutorial missing something? Do I have to install Express in order to view the page web?
Sorry again, english is not my native langage.
Thanks a lot for your answers.
With this line in your html
<script src="app.js"></script> <!-- wrong! -->
you try to run your nodejs program in your browser's javascript interpreter. You need to run it on your server instead. Your browser gacks on the require() operations because those are made to work in nodejs on your server.
Try removing the line from your html, and try doing something like this on your server's command line, then visiting http://localhost:1337 from your browser.
node app.js
The fact that browsers and nodejs support the same language is a bit confusing as you figure this all out. The language is the same but the two runtime environments are quite different. Be patient. You'll get it.
The app.js nodejs program you showed us should function correctly. In its if (name) branch it handles the request coming from the $.get() operation in the browser. In its else branch it delivers the html file to the browser.
And, it has to be said, doing more than just this kind of tutorial with nodejs alone -- without express or some other webserver framework -- gets to be a huge pain in the xxx neck, enough of a pain in the neck that you'll be tempted to develop your own framework.
Edit You have this line twice
res.writeHead(200, {'Content-Type': 'text/plain'}); /* wrong! */
Change both occurrences to
res.writeHead(200, {'Content-Type': 'text/html'});
The Content-Type: text/html header tells your browser to interpret your html file as html, not raw text.

Make favicon.ico appear at the top bar of the web page

I am using node.js to run the server. Always when I make a request to it actually there are occur two requests, one of which is an ordinary one, which was truly made and one is request/favicon.ico. So I tried to send favicon.ico back because I want it to appear in the top bar. But it just doesn`t appear there.
What am I doing wrong? Here is my code:
var http = require("http");
http.createServer(onRequest).listen(7777);
console.log("Server is running now.....");
function onRequest(request, response)
{
console.log("A user made a request" + request.url);
response.writeHead(200, {"Context-Type": "text/plain"});
response.write("Here is some data");
response.end();
}
And I put file favicon.ico into the same folder my server.js is.
This question:Set favicon in HTTP server? is not appropriate for me since the answer and code in answer, which were accepted, for it don`t work for me.
This should work
var http = require("http");
var fs = require("fs");
http.createServer(onRequest).listen(7777);
console.log("Server is running now.....");
function onRequest(request, response)
{
console.log("A user made a request" + request.url);
if (request.url === '/favicon.ico') {
var fileStream = fs.createReadStream("./favicon.ico");
return fileStream.pipe(response);
}
response.writeHead(200, {"Context-Type": "text/plain"});
response.write("Here is some data");
response.end();
}
But as you can see you have to create a special case for each url you want to handle. I recommend using a framework like express which will make things easy for you.
Also with framework you can have favicon in static directory so you won't have to explicitly read from file system on each request for static files.
You can do this by adding this line in your html page in head tag.
<link rel="icon" type="image/png" href=favicon.ico>
If you use http module directly then you will have to inspect the request object on every request and serve the favicon file yourself for all requests requesting favicons.
In your example, you will have to test the request object in the onRequest() function and serve a favicon for some requests, and your original stuff for the rest of the requests.
If you use Express or some other framework with Connect-compatible middleware, then you'll be able to use modules for that like this one:
https://www.npmjs.com/package/serve-favicon
If you want to use just the http module without Express or any other higher level framework, see this answer for examples on how to serve static images with http (and also with Express) that will help you with that:
How to serve an image using nodejs

Can't load local files when using NodeJS server

I'm very new to NodeJS, and I'm currently playing around with it (and websockets), so this question might be a bit dumb. Anyway, I'm following a tutorial which has given me a simple app.js containing the following:
var fs = require('fs')
, http = require('http')
, socketio = require('socket.io');
var server = http.createServer(function(req, res) {
res.writeHead(200, { 'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}).listen(8080, function() {
console.log('Listening at: http://localhost:8080');
});
socketio.listen(server).on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg);
socket.broadcast.emit('message', msg);
});
});
In my index.html I'm trying to load some js and css files, but I can't seem to load them. The files are inside a js folder which is in the same directory as my app.js and index.html, and I'm trying to load them like so:
<script src="/js/script.js"></script>
If I look at the response from the request in my browser, it's returning the content of index.html.
Again, sorry if this question is silly, but I'm stuck and have no clue where to look.
Thanks!
A web server in node.js does not serve ANY files by default (unlike some other web servers). So, if you want js files to be served, you have to define a web server route that will serve them. The code you show returns index.html for all incoming requests coming into that http server so, it should be no surpise that when a request comes in for /js/script.js, your web server sends out index.html.
A typical framework to use with node.js for web serving is Express and it has express.static() that can be used to define a route that will cover all your static files or all files in a particular directory. You could, of course, code your own static file handling or find some other module to do that also. The point is that you have to write or configure some code to serve your static resource files. That is not done for you automatically by the node.js http server.
you can specify to the server in which folder to look for what
for static files such as css, images you can use
public directory, you can provide your custom directory, but it's better to use public ,same goes for views
always require
const PATH = require('path')
app.use(express.static(PATH.join(__dirname, 'public')));
for template files such as .ejs, .html, .jade use
app.set('views', PATH.join(__dirname, 'views'));

Express js routing is downloading file and not rendering it

I am trying to implement a router on the server side with node.js and express.js.
I want to serve a file statically, but I already got this to work for a index.html file I created. No problems there.
My setup has tons of fileName.csp files (i.e. they end in .csp). Anyways, when I try to access a .csp file in the browser (inside it is really just a .html page - but the server side language must have it as a .csp file extension) but when I try to access it, the browser (google chrome) downloads the .csp file instead of rendering it!
I could really use some help since I'm new to all of this.
the line of code that is allowing the download of the .csp file, the code that exposes the directory where the .csp files live, is
app.use('/static', express.static('D:/CACHESYS/CSP/cah/'));
below is pretty much the whole snippet of code
var http = require('http');
var express = require('express');
var app = express();
app.use('/static', express.static('D:/CACHESYS/CSP/cah/'));
app.listen(3000, function() {
console.log('listening on port 3000');
})
app.get('/home', function(request, response) {
response.end('going to /home');
})
app.get('/csp/cah/MARS.csp', function(request, response) {
response.end('Trying to navigate to /csp/cah/MARS.csp');
})
p.s. the actual file path that is being downloaded is
D:/CACHESYS/CSP/cah/fileName.csp
just to give some more context for the question.
any help is appreciated
thanks!
You need to tell express what content type a .csp file is. You can do this with the following line:
express.static.mime.define({
'text/html': ['csp']
});
Although, if the file is an HTML file, it should probably have the .html extension. Also, if you are simply serving static files it is good practice to use an HTTP server like nginx or Apache to do that, rather than Node.js.
The reason this works is express will set the header Content-Type: text/html. This tells the browser it is HTML and it should render it as such. By default if a browser comes across a content type it doesn't recognise, it simply downloads it.

Angularjs + node + socket.io on localhost

I'm using an AngularJs, node & socket.io to write an app where I want to have some shared data in my different clients. I'm looking at this example: https://github.com/mhevery/angular-node-socketio
I get everything up and running and it works fine if I go to the location of my index.html in my file system (c:/user/angularnodesocket/index.html), but when I go to localhost:8888 the site still shows but the angular stuff is not interpretated.
I get this error on localhost
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8888/bower_components/angular/angular.js". localhost/:4
Uncaught SyntaxError: Unexpected token < :8888/bower_components/angular/angular.js:1
Can anyone help me with what's going on here?
//G
In that example you are using the following code
http.createServer(function (request, response) {
fs.readFile(__dirname+'/public/index.html', function (err, data) {
if (err) throw err;
response.setHeader("Content-Type", "text/html");
response.end(data);
});
}).listen(8888);
returns index.html whatever the request is. Your browser requests angular.js file, but index html is returned instead which causes the error messages you see.
You have to modify server.js code to support static files.

Resources