I have the following directory structure in Linux with just 3 files in it:
/home/nikhil/test_img/
server.js
page.html
pic.jpg
This is a simple node.js hello world setup without using express or any other library
Code for server.js
var http = require("http"), fs = require('fs');
var path = require('path');
var root = path.dirname(require.main.filename);
var filePath = path.join(root + '/page.html');
var port = 8889;
function onRequest(request, response) {
fs.readFile(filePath, function (err, html) {
if (err) {
throw err;
}
response.writeHead(200, {'Content-Type': 'text/html'});
response.write(html);
response.end();
});
}
http.createServer(onRequest).listen(port, function () {
console.log("Server has started at port " + port);
});
This simply creates the server which displays page.html on any request to localhost:8889
Code for page.html
<html>
<head><title>Page</title></head>
<body>
<h1> Hello World </h1>
<img src="pic.jpg" alt="image">
</body>
</html>
This is a simple webpage with Hello World heading and an image.
Now, the error is that the image does not get displayed when the page is loaded when I hit localhost:8889 on my browser. But, the image is displayed when I simply open the webpage through my browser (not via node).
I have also tried changing the src to
"/home/nikhil/test_img/page.html"
"file:///home/nikhil/test_img/page.html"
"localhost:8889/page.html"
But, none of these work
Also, I tried printing my location in javascript using <script>alert(document.location.pathname);</script>
The path printed was
/
Whereas, when I ran the page directly in my browser (without node), it was
/home/nikhil/test_img/page.html
Where do I need to put the image file for this to work?
Your code says that each request should serve the file that corresponds to filePath i.e. the html file page.html. This is fine for the page request itself, but the img tag in your html page creates a separate request for the image pic.jpg which should exist in the same path as the page. But instead of serving the img file, which means your request handler would return something with header Content-type: image/jpg, your request handler again responds with the html page's contents and header Content-Type:text/html.
You need to differentiate what to serve, based on what is being requested.
Related
I am running node project with html and javascript. How can I display the alert box in html.
My html (index.html)
<!DOCTYPE html>
<html>
<head>
<script src="./watch.js"></script>
</head>
<body onload="showBox()">
<h1>Heading</h1>
<p>Paragraph</p>
</body>
</html>
watch.js
function showBox(){
alert("this is alert box");
}
server.js
var http = require('http');
var fs = require('fs');
const PORT=8080;
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(PORT);
});
Error
I think that the problem is that you are not telling nodeJS where your statics files are.
For me, the simplest way is to set the server with Express
$ npm install express
And then setting up the server and where your static directory is:
var express = require('express');
var app = express();
//setting middleware
app.use(express.static(__dirname + 'public')); //Serves resources from public folder
var server = app.listen(5000);
There are other ways to doit using Native NodeJS, here are some resources:
Nodejs.org - How to serve static files
Also, you can write the script directly in your html file:
<!DOCTYPE html>
<html>
<head>
<script>
function showBox(){
alert("this is alert box");
}
</script>
</head>
<body onload="showBox()">
<h1>Heading</h1>
<p>Paragraph</p>
</body>
</html>
Your server is only ever returning index.html, no matter what path is requested. So, your watch.js is never loaded. The contents of index.html are returned instead of watch.js.
Either handle the other paths in your server code, or use something like Express.static, which does this for you.
Your http server is only outputting the index.html file. You need to either put all your client-side code in that file, or edit your server to load the watch.js file and make it able to send either page.
The first is simpler. Here's a basic example for the second. Most browsers will assume the mime-type by the extention.
Also, change your html for the script name from "./watch.js" to just "watch.js".
I simplified this down to be easier to understand... also const is deprecated and wont work on newer versions of node.
Specifying the mime header like you did is more compatible (Chrome and Firefox will assumebased on file extension, but for example Opera does not, or didnt used to).
var http = require('http');
var fs = require('fs');
var doc = {}
doc['/index.html'] = fs.readFileSync('index.html');
doc['/watch.js'] = fs.readFileSync('watch.js');
var server = (request, response)=>{
response.end(doc[req.url]);
}
http.createServer(server).listen(8080);
So I'm very new to node.js and javascript, and i made a server that works great by loading up an html file on request. This html file does not contain any of it's own data, it simply sources from the internet and displays some images and text i wrote. I've decided to make the site play an audio file when it is opened. I know this is done easily with the <audio> tag in html5 but the src="" lets me take a file from the computer and place it there, of course when i open the site from another computer the file obviously isn't found and thus isn't played. I figure the audio file must be kept as a variable on the server and passed into the html file's <audio src= > tag. How do i do this? It is an .mp3(but i can get it to any other audio format) file about 30 seconds long. I just want it to play when the site is loaded from another computer(over the internet). Also how would i go about doing the same with pictures or any other data that i don't want to source from the internet but rather keep as data in my server?
var http = require('http');
var fs = require('fs');
var simpleServer = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type":"text/html"});
fs.readFile('./Picture.html', null, function(error, data){
if(error){
response.writeHead(404);
} else{
response.write(data);
}
response.end();
})
});
simpleServer.listen(80, '0.0.0.0', function() {
console.log('Listening to port: ' + 80);
});
console.log("Server running...");
Short Answer
Bypassing using HTML altogether, you can also simply serve the audio file instead of Picture.html:
fs.readFile("./audiofile.mp3", function(error, data) {
if (error) {
response.writeHead(404);
} else {
response.writeHead(200, { "Content-Type": "audio/mpeg"});
response.end(data, 'utf-8');
}
});
Note:
You will have to replace the filename audiofile.mp3 and the content type audio/mpeg to their appropriate values for the file you want to send.
Check Mozilla's Complete List of MIME Types for a full list of file extensions and their associated content types.
Better Answer:
The http module is fairly low-level and is unnecessarily complicated if you're learning.
You can install express.js to your project using the command npm install express --save.
With express your code simplifies to:
const express = require('express');
const app = express();
const port = 80;
app.get('/', (request, response) => {
response.sendFile(__dirname + '/Picture.html');
});
// Anything put in the public folder is available to the world!
app.use(express.static(__dirname + '/public'));
app.listen(port, () => {
console.log(`Listening on port: ${port}`)
});
Then you just have to place all your files into a folder called "public" under your project directory and you can call them from HTML!
I have a node.js server with the following code:
var http = require('http'),
fs = require('fs'),
index = fs.readFileSync(__dirname + '/index.html');
var app = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(index);
});
app.listen(80);
When I use an tag in index.html, no images will show:
<html>
<body>
<img src="settings.gif" />
</body>
</html>
The image is in the same directory as the server.js file and index.html
Edit: Images will show if I use a full URL to another site. Example:
<img src="http://yellowicons.com/wp-content/uploads/Gear-Icon-2.png" />
Perhaps you may decide to separately create a public/images directory beneath and copy the settings.gif as well as any other images into the image directory that can be publicly viewable.
Next you will need to make known to node where the static reference for the public directory is by adding these 2 lines into node.js
var publicDir = require('path').join(__dirname,'/public');
app.use(express.static(publicDir));
After which, the image could be tagged in the html as
<html>
<body>
<img src="images/settings.gif" />
</body>
</html>
Try using absolute path. In case of failure, keep the image file in public/images directory. and use this address:
<img src="http://localhost:3000/images/Heading.png" />
I guess your server doesn't know where your images are, I don't see where your code specifies that. I suggest you use nodejs with express to handle all your routes, just google it and have tons of examples.
Good luck
Before access image fine html static page we have to add static folder location in the nodejs middleware using app.use() method
staticPages
| - image.png
| - index.html
code:
server.js
app.use(express.static(path.join(__dirname, "staticPages")));
index.html
before server start: <img src="./image.png" />
after server start: <img src="http://localhost:3000/image.png" />
I hava an html file that execute js file inside.
Now I want to run this with Node.js server.
I can see that it write the html file in it (it write 'hi (:') but ignored the js file.
this is the 'server.js' file:
var fs = require('fs');
var http = require('http');
var content;
//read the file
fs.readFile('index.html', function read(err, html) {
if (err)
{
throw err;
}
content = html;
http.createServer(function(request,response)
{
response.writeHead(200,{"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8081);
console.log("listening on port 8081");
});
and this is the 'index.html' file:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="script.js"> </script>
<script> </script>
</head>
<body>
<div id="empty">
hi :)
</div>
</body>
</html>
Thanks for your help! (:
You've created a server that responds to every single request with the contents of index.html--so when the <script> tag asks the server for the script.js file, the server incorrectly sends it index.html again.
In your createServer handler, you'll want to look at the incoming request and figure out which file the request is asking for, and send different data back accordingly.
To handle this situation more robustly, where you don't have to have an if statement for every file you might want to send, you can use an abstraction over your createServer handler to detect and send static files automatically. This question contains several solutions that may help put you on the right track.
I am using nodejs with the expressjs module to create a webserver.
My current setup is this
var express = require("C:/Program Files/nodejs/node_modules/express")
var app = express();
var server = require('http').createServer(app).listen(80);
var io = require('C:/Program Files/nodejs/node_modules/socket.io').listen(server, {log:false});
var path = require("path");
fs = require("fs");
is there a way using
app.use(function(req,res,next){
//code
})
to get where a request came from? Eg, if on an html page, you have the script tag
<script src="test.js"></script>
it sends a request to retrieve test.js, can I use the req argument to see that the request for test.js came from the html page and get the full filepath of the html page?
EDIT: I'm trying to write a function that serves the correct index file (index.html/.htm/.php etc if you just enter a directory into the url ("localhost/tests/chat/"), but the problem then is, when it requests the javascript file from the index page, it goes back 1 directory too far (searches for "localhost/tests/test.js" instead of "localhost/tests/chat/test.js"), and only works if you directly type the filename into the url ("localhost/tests/chat/index.html").
My function:
app.use(function(req,res,next){
var getFullPath = path.join("public",req.path);
console.log(req.path);
if (fs.existsSync(getFullPath)) {
if (fs.statSync(getFullPath).isDirectory()) {
getFullPath = path.join(getFullPath,"index.html");
}
res.sendfile(getFullPath);
} else {
res.send("404 Not Found");
}
});
I realise you can use
app.use(express.static(__dirname + '/public'));
but this creates a problem for me with my custom php parser module so that's not really an option
I was able to use req.headers.referer to get where the javascript file was being asked from and therefore point to the correct location of the javascript file.
getFullPath = path.join("public",req.headers.referer.split(req.host)[1],path.basename(req.path));