This might be a dumb question: I have an .html file with one <script> (main.js) initially loaded on it, which programmatically add structure on that html file. Also this script adds another which uses that structure to draw some charts.
Then, I am serving this html with node. Also I am serving those scripts in my server.js like this:
app.get('/', function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('./index.html', 'utf8', function(error, data) {
if (error) {
res.writeHead(404);
res.write('File not found!');
} else {
res.write(data);
}
res.end();
});
});
app.get('/main.js', function(req, res) {
res.sendFile(path.join(__dirname + '/..' + '/main.js'));
});
And so...
Everything is working great. User can't have interaction with the page, so everything will remain the same .
Now, I want to develop some unit tests on that .html (like check elements, values, etc.).
I did a lot of research, but I can't find the answer or some clue to lead me, given this situation.
How should I do it?
Am I structuring things wrongly to accomplish my goal, or not following good practices?
Related
I have been working on avoiding # in Angular app with ExpressJS serverside.
I have researched how to enable html5mode and it worked great. But whenever there is another 'get' request to retrieve data from another url such as /api/services, it seems like somehow broken and do not provide data properly to the page.
Here's what I have done in express end.
router.get('/*', function (req, res, next) {
res.render('index');
});
router.get('/api/service-edit', function (req, res, next) {
Service.find(function (err, services) {
if (err) {return next(err);}
res.json(services);
});
});
I am not 100% sure, but what I guess is '/*' causes a problem for the server in reading api urls.
I am wondering if any of you have an experience in this problem and a solution to figure this out.
Thank you for your time.
In expressjs the routing rules are matched in the order you present them in the code. So the '/*' rule is always matched first and the second rule is never reached.
Putting the second rule before the first one will probably solve the problem.
Hope it helps.
So I am just learning and I am trying to build a web app using node, I know I could use express but I am trying to build it all using Node to get a better understanding.
The problem is I cant get the main.js page to load on the app.
I have a router module that builds the page eg
function home(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(fs.readFileSync('./views/header.html'));
res.write('<style>' + fs.readFileSync('./css/styles.css') + '</style>');
res.write(fs.readFileSync('./views/startpage.html'));
res.end(fs.readFileSync('./views/footer.html'));
};
and the script tag is in the footer partial just before the closing body tag, would i need to load it a different way ?
Here is the full app if this is not enough information, thanks
https://github.com/naassi/taxi-log
You probably want a static file server for all your css and javascript files. Instead of sending the CSS file content in home, include
<style>./css/styles.css</style>, and answer the request for *.css files with the appropriate file:
function staticServer(req, res) {
fs.readFile(__dirname + req.url, function (err,data) {
if (err) {
res.writeHead(404);
res.end(JSON.stringify(err));
return;
}
res.writeHead(200);
res.end(data);
});
})
In footer, you want to load a .js file - your Node server is responsible for serving that, just like it handles a request for e.g., home.
If you're learning Node, try to stay away fron Sync functions, they block the event loop, and defeat Node's good parts :)
I would like to protect images which are uploaded. When users upload images, they are saved to the following path:
public/dogs/{userId}/{imageName}
Each user has it's own directory where images are saved. I've figured out I can easily serve those images if I do something like this but the images are then accessible by everybody:
app.use(express.static('public'));
My user validation works in the way that I check does the request url contains /api/admin in the path. Example:
router.get('/api/admin/dogs', dog.getAll);
I would like to serve the images in the similar way to just allow admin to access them. Is it possible to have something like this:
router.get('/api/admin/dogs/images/:userId/:imageName', image.getOne);
Thank you for your help.
There is a sendFile function available on response object. You can use it to send the file based on you user validation.
It would be something like this:
router.get('/api/admin/dogs/images/:userId/:imageName', function(req, res, next){
currentUserHasAccessTo(userId, imageName, function(err) {
if (err)
next(err)
else
res.sendFile(`public/dogs/${userId}/${imageName}`)
})
});
currentUserHasAccessTo is your validation function that would query a database or something else.
If an error is returned, it will be passed to the error handler middleware so that it can show a default image or an error page.
you can also use stacking of handlers:
router.get('/api/admin/dogs/images/:userId/:imageName', function(req, res, next){
currentUserHasAccessTo(userId, imageName, function(err) {
if (err)
next(err); // or res.send(401) if unauthorized
else
res.next() ; // this will "jump" to the express.static below
})
, express.static('public') });
In this case, you have two handlers for a single route. The second one will be reached only if next() is called...
I'm fairly new to Node.js and am having trouble understanding the way to go about loading libraries or files, in runtime.
Apparently, it is a bad idea to load files in runtime using Node.js's native "require" function because it is blocking i/o, and therefore should not be used from within request handlers. So, I'm assuming something like this is to be avoided:
var http = require('http').createServer(function(req, res) {
var file = require('./pages/'+req.url);
res.end();
}).listen(8080);
So then is there a way to require files in runtime, in a non-blocking/asynchronous way?
I don't think it would always be possible to load files in "boot time" rather than runtime because like in the example above, the only way to know what file to load/require is by getting the name through the req.url property.
So that seems like the only option. Unless, all the files in the folder are preloaded and then called upon by name, in the callback (By using fs.readdirSync or something to iterate through all the files in the folder and compare the gotten files' names to the req.url property), but that seems wasteful. "Preloading" all the files in the folder (maybe around 50 files) and then only using 1 of them, doesn't seem like a good idea. Am I wrong?
Either way, I would just like to know if there is a way to require files in runtime in a better, non-blocking/asynchronous way.
Thank you!
The function require() is generally used for caching modules or configuration files before most of your application runs. You can think of using require() somewhat like this:
var file = fs.readFileSync('/path');
// depending on the file type
eval(file);
JSON.parse(file);
The reason it is done this way is so that dependencies are loaded in order. If you want to read a file after initializing the application, you should use a asynchronous read, and respond in the callback like this:
var http = require('http');
http.createServer(function(req, res) {
fs.readFile('./pages/' + req.url, function(err, data) {
res.end(data);
});
}).listen(8080);
If you needed to check if a file existed, then you could use fs.stat() to check the existence of a file, rather than querying the directory.
var http = require('http');
http.createServer(function(req, res) {
var file = './pages/' + req.url;
fs.stat(file, (err, stats) {
if (err || !stats.isFile()) {
res.writeHead(404);
res.send();
return;
}
fs.readFile(file, function(err, data) {
res.writeHead(200);
res.end(data);
});
});
}).listen(8080);
I've recently ran into a very interesting problem while writing a web app with node.js.
Essentially, all I am doing is serving the index.html page to the client.
Here is the code:
var http = require('http');
var url = require('url');
var fs = require('fs');
var util = require('util');
var server = http.createServer(function(req, res){
var path = url.parse(req.url).pathname;
if(path == '/'){
console.log("LOADING INDEX...");
openIndex(req, res);
console.log("LOADING COMPLETE.")
} else {
res.write("Something went wrong...");
res.end();
}
}
);
var openIndex = function(req, res){
fs.readFile('./index.html', function(error, content){
if(error){
res.writeHead(500);
res.end();
}
else{
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(content, 'utf-8');
}
});
}
I've put some debugging statements just before and after the index.html page loads: "LOADING INDEX..." and "LOADING COMPLETE".
Now, I have shared the link to my server with my Facebook friends so they can see my app. Most of the time, everything works as it should, but once in a while I get this error:
LOADING INDEX...
This type of response MUST NOT have a body. Ignoring data passed to end().
and just now I've also gotten:
LOADING INDEX...
This type of response MUST NOT have a body. Ignoring write() calls.
The process never raches the "LOADING COMPLETE" statement.
I've tried to reproduce this countless times (accessing my app on different machines, browsers, devices, OS-versions) but every time it works as it should.
I've looked around for other people having this problem, and it seems that somehow, a body is getting into a GET response? I'm not entirely sure what this means or how to fix my code to prevent that from happening. Also, I'm not sure what the clients that produce this error see? Do they get to see my app? (i.e. are these just warnings and as far as they are concerned everything is fine?)
Any help with this will be greatly appreciated.
Xaan
If you're just using a static index.html, why not use express.static to serve it automatically?
app.use("/index.html", express.static(__dirname + '/index.html'));
This would cause expressjs to automatically handle HEAD requests, which should solve your problem.