Reputation: 3098
Edit: I know using express or whatever would be easier, but this is all a learning exercise, so sorry if this is all massively convoluted, haha!
Edit 2: It appears (after adding a few console logs for debugging) that it seems the problem has something to do with the fact that when the browser makes one request to the server (say, for style.css), it makes another request (e.g. for login-fail.js) before completing the response for the first request. It seems these multiple requests from the browser cause some sort of problem, each subsequent request preventing the previous from completing. Yikes, I need help.
Edit 3: After some debugging, it appears that the pathname variable does not change its value upon each request. For some reason, pathname's value persists over each request and this makes every request's response the same - stranger still, the value for uri changes over each request (and the uri is what gives the pathname its value...) still trying to find out why this bizarre behaviour is happening.
So I've been having this problem when the server makes requests for external .js and .css files linked to specific .html files. The responses are always inconsistent. For instance, sometimes the code will run perfectly, other times the css will load and not the js, sometimes both, sometimes neither. I am not able to determine whether this is because my code is synchronous, or for some other reason. Here is my code:
Server.js
//Module requires
var http = require("http"),
fs = require("fs"),
path = require('path'),
url = require('url'),
invoke = require("./invoke");
//Object "MIMETYPES"
//Maps relationships between file extensions and their respective MIME Content-Types
var MIMETYPES = {
".html": "text/html",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".png": "image/png",
".js": "text/javascript",
".css": "text/css"
};
//Object "invokeOptions"
//Options passed to Invoke() function for POST requests
var invokeOptions = {
postData : "",
uri : ""
}
var PORT = 8888;
//HTTP Server Begin
http.createServer(function(req, res) {
var uri = url.parse(req.url).pathname;
pathname = path.resolve(__dirname, "..") + uri;
console.log("Recieved " + req.method + " request for : " + uri);
invokeOptions.uri = uri;
//GET requests wrapper
if (req.method == "GET"){
//Invoke() function handler for GET requests
if (path.extname(pathname) == ""){
invoke.invoke(invokeOptions, req, res);
return;
}
//Static file server for GET requests
fs.exists(pathname, function(exists) {
if(!exists) {
console.log("Requested file \'" + pathname + "\' doesn't exist.");
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('404 Not Found\n');
res.end();
return;
}
var contentType = MIMETYPES[path.extname(pathname)];
res.writeHead(200, {"Content-Type" : contentType});
console.log("Current URI: " + uri + " has content type: " + contentType);
fs.createReadStream(pathname).pipe(res);
return;
});
}
//POST requests wrapper
if (req.method == "POST"){
var postData = "";
req.on("data", function(postPacket) {
postData += postPacket;
});
req.on("end", function() {
invokeOptions.postData = postData;
invoke.invoke(invokeOptions, req, res);
return;
});
}
}).listen(PORT);
console.log ("Server listening on port: " + PORT);
Invoke.js - This handles requests for non-files, that is requests for functions on the server
var fs = require("fs"),
querystring = require("querystring"),
path = require("path");
function invoke (options, req, res){
process.stdout.write("Invoking function --> ");
if (options.uri == "/"){
console.log("Index");
res.writeHead(200, {"Content-Type" : "text/html"});
fs.createReadStream("../index.html").pipe(res);
return;
}
if (options.uri == "/login"){
console.log("Login");
fs.readFile(path.resolve("../users.json"), "UTF-8", function(err, data){
if (err) throw err;
var json = JSON.parse(data);
var user = querystring.parse(options.postData).username,
password = querystring.parse(options.postData).password;
console.log("Submitted Username: " + user + "\nSubmitted Password: " + password);
if (json.users[0].username == user && json.users[0].password == password){
res.writeHead(200, {"Content-Type" : "text/html"});
fs.createReadStream("../app.html").pipe(res);
return;
}
else {
res.writeHead(300, {"Content-Type" : "text/html"});
fs.createReadStream("../login-fail.html").pipe(res);
return;
}
});
}
else {
console.log("Error! Bad request.");
res.writeHead(400, {"Content-Type" : "text/plain"});
res.end("Error 400: Bad Request. \nThere is no function corresponding to that request.");
}
}
exports.invoke = invoke;
Login-fail.js - This is the code that hardly ever loads
$(document).ready(function() {
var current = 3;
var countdown = $(".countdown");
function down (){
current--;
if (current != 0){
countdown.text(current);
}
else {
clearInterval(interval);
window.location.replace("./");
}
}
var interval = setInterval(down, 1000);
});
Basically, the index.html file is a form which accepts a username and password, compares the submitted POST data to a json file, and if it matches the hashes in the json file it requests app.html, otherwise it requests login-fail.html. When the login-html file is called, it has linked to it css and js which when requested hardly ever run!
Also, I thought it should be noted that the console.logs for "content-type" when requesting the css is 'text/javascript' when it doesn't work. Any help would be massively appreciated!
Upvotes: 0
Views: 399
Reputation: 3098
Holy crap.
Pathname wasn't being declared as a variable each request, because I used a ;
instead of a ,
I'll go die now ladies and gents.
Upvotes: 2
Reputation: 106696
The relative paths you're using in your login-fail.html
are probably not resolving correctly because the URL path doesn't change (/login
), so the browser is looking for /login/css/style.css
and /login/js/login-fail.js
. Try modifying your login-fail.html
to use absolute paths instead of relative paths.
Upvotes: 0