I am attempting to create a basic webserver with Node.JS, but running into an issue with properly serving images.
var server = http.createServer(function (request, response){
if(request.url === '/') {
fs.readFile('public/index.html', 'utf8', function(errors, contents){
response.write(contents);
response.end();
});
} else {
fs.readFile("public" + request.url, 'utf8', function(errors, contents){
if (!errors) {
response.end(contents);
} else {
console.log('Failed to read file: /public' + request.url);
response.writeHead(404);
response.end();
}
});
}
});
Everything works fine, apart from if you go to view the image it attempts to download it (which I believe is corrupted - cant open it), which is not what I want, I wish for the images to be served properly in the browser (not via a tag)
Bonus points: I need to be able to correctly give the proper headers (Do I need just a switch statement and set them via that?), as chrome is giving off warnings
Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost/css.css".
You can use expressjs : http://expressjs.com/
const express = require('express')
const app = express()
app.get('/', (req, res) => res.sendFile('public/index.html'))
app.use(express.static('public'))
app.listen(8080, () => console.log('Example app listening on port 8080!'))
NB :
Your code is unsafe : "public" + request.url. Your users can get all files of your server : fs.readFileSync("public/../../../README.txt");
You will get error on parent folder.
Error: ENOENT: no such file or directory, open 'C:\README.txt'.
Related
So I'm creating a game with HTML, css, and javascript, and I'm trying to incorporate template engines/ajax in this task. I made a server which if I run in cmd and then open up google chrome and type 'localhost:3000' in the address line, it is supposed to direct me to the main.html page.
However, when I type 'node server.js' in cmd, it runs properly but when I enter 'localhost:3000' in the browser it says the page does not exist. I'm not sure what went wrong. If I were to manually double click on the html file in my folder, it works, but I'm trying to get it to load by running a server.
I have three folders (img, node_modules, and pages) and 2 json packages which were created by installing express and pug. It's hard to explain my folder paths and code here, so I have a link to a folder containing my files/sub folders and it also gives a clearer view of the path in my directory: https://github.com/jessaisreal/game
It wouldn't let me upload the node_modules folder as it was too big, but I automatically got it from typing 'npm init', 'npm install express' and 'npm install pug' into the cmd line in the folder.
I'm assuming something is wrong with my server.js file or the way my folders are set up. I'm really desperate to get my program working and would appreciate any help. I have no idea why my html page isn't loading. I'm also not sure if I handled the GET request for getting specific fonts correctly.
I cut down my program as much as I could. There are several html and css files, but only included create and main here for simplicity. Again, I would appreciate any help or a push in the right direction!!
server.js:
const http = require('http');
const fs = require("fs");
const pug = require("pug");
//user pug functrion to render through the create Page
const renderMain = pug.compileFile('pages/main.pug');
const renderCreate = pug.compileFile('pages/create.pug');
//Helper function to send a 404 error
function send404(response){
response.statusCode = 404;
response.write("Unknown resource.");
response.end();
}
// Helper function to send 500 server error;
function send500(response){
response.statusCode = 500;
response.write("Server error.");
response.end();
}
// initilize the server
const server = http.createServer(function (request, response) {
//console.log(request.method+" -> "+request.url); test about the income request
// handle the get request
if(request.method === "GET"){
if(request.url === "/" || request.url === "/main"){
let data = renderHome("./pages/main.pug",{})
response.statusCode = 200;
response.end(data);
}else if(request.url === "/main.js"){
//read main.js file and send it back
fs.readFile("main.js", function(err, data){
if(err){
send500(response);
return;
}
response.statusCode = 200;
response.setHeader("Content-Type", "application/javascript");
response.write(data);
response.end();
});
}else if(request.url === "/main.css"){
//read css file
fs.readFile("main.css", function(err, data){
if(err){
send500(response);
return;
}
response.statusCode = 200;
response.setHeader("Content-Type", "text/css");
response.write(data);
response.end();
});
}else{
send404(response);
return;
}
}
});
//Server listens on port 3000
server.listen(3000);
console.log('Server running at http://127.0.0.1:3000/');
I highly suggest that you use expressjs for better organizing your project and this issue will be gone
In my client side javascript, I request private content if the user is authorised (using firebase auth) as per below:
firebase.auth().onAuthStateChanged(user => {
if (!user) {
ui.start("#firebaseui-auth-container", uiConfig);
}
if (user) {
import("/private.js").then(module => {
console.log(module.default);
});
}
});
All users are served index.html from the public firebase hosting URL, but only when a user has been authorised do they request the private content. My firebase.json redirects to handle this:
"rewrites": [
{
"source": "**",
"function": "app"
}
]
I am struggling to set up a firebase functions based express backend to serve the javascript. (I haven't added auth checking yet because I want to get it working simply serving the js first).
My firebase function looks like this:
const fs = require("fs");
const functions = require("firebase-functions");
const express = require("express");
const app = express();
app.get("/private.js", (req, res) => {
fs.readFile("private.js", "utf8", function (err, data) {
if (err) throw err;
res.send(data)
});
});
exports.app = functions.https.onRequest(app);
However, when a user gets authorised and the client tries to dynamically import private.js I get the following error: Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. How do I properly set the MIME type to serve js files?
You need to tell the browser that an error occurred, so that it does not try to parse the response as JavaScript. You can do that by sending a status code starting with 4 (client error) or 5 (server error). Here is an example:
app.get("/private.js", (req, res) => {
fs.readFile("private.js", "utf8", function (err, data) {
if (err) {
res.status(403).send('Could not load the data.');
} else {
res.send(data);
}
});
});
I worked it out. I need to use:
res.setHeader("Content-Type", "text/javascript"); //Solution!
res.writeHead(200);
res.end(data);
And it works fine.
Try this
res.type('.js');
res.send(data);
I would like to know why is there a difference when I launch my project with NodeJS and when I launch directly with the HTML file.
Here is what I am supposed to have (with the HTML file) :
And here is what I have through NodeJS :
As you can see, it seems that the VueJS variable is not working anymore.
I don't know why because, i just create a short NodeJS program to launch this HTML file. I know that it is not a huge problem and can be easily solved.
Here is my JS program
var http = require ('http');
var fs = require('fs');
var port = 3000
var server = http.createServer(function(req,res){
res.writeHead(200,{'Content-Type': 'text/html'})
fs.readFile('index.html', function(error,data){
if (error) {
res.writeHead(404);
res.write('Error file not found');
}else {
res.write(data);
}
res.end();
})
})
server.listen(port,function(error){
if(error){
console.log('Something went wrong', error);
}else {
console.log("server is listening on port 3000");
}
})
Thank you guys in advance for your help. I look forward to see your responses.
I am new to nodeJS. I am trying to load an index.html page onto my 8080 port and have this:
var http = require('http');
var fs = require('fs');
var PORT = 8080;
function home(req, res) {
if(req.url == '/'){
fs.readFile('index.html', function read (err, data) {
res.writeHead(200, {'Content-type' : 'text/html'});
res.write(data);
res.end();
});
}
};
var server = http.createServer(function (req, res) {
home(req, res);
});
server.listen(PORT);
I have 3 files in the same directory: index.html, style.css, server.js. I start up the server and the page will not load until after I hit cntrl + c. Why is this?
You have written the data to the response, but you have not finished the response. Put res.end(); after your res.write function.
Without this, the browser keeps waiting for more data from the server. When you shut down the server with Ctrl-C, the server closes the connection, and the browser renders what it received.
If you are new to Node, I would recommend looking into something like Express, which handles a lot of important things like routing (what URLs go to which pages) for you and will save you a lot more if statements in the future.
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!