Node JS not serving the static image - javascript

I have already added the codes for serving an image on my node server but it seems to not serve images in the HTML when connecting to Node. I have also external CSS and JS that are being served correctly. Here is the fragment of my code in Node (See below). Thank you in advance!
var server = http.createServer(function(req, res) {
var pathname = url.parse(req.url).pathname;
var ext = path.extname(pathname);
var handler = handlers[req.url];
if(ext) {
if(ext === ".css"){
res.writeHead(200, { "Content-Type" : "text/css" });
}
else if(ext === ".js") {
res.writeHead(200, { "Content-Type" : "text/javascript" });
}
else if(ext === ".jpg") {
res.writeHead(200, { "Content-Type" : "image/jpg" });
}
res.write(fs.readFileSync(__dirname + pathname, "utf8"));
res.end();
}
else if(handler) {
handler(req, res);
}
else {
res.writeHead(404, { "Content-type" : "text/plain" });
res.end();
}
});
server.listen(80);

I've seen a lot of questions like this on Stack Overflow when someone tries to implement their own static file server instead of using Express or something that works, and fails to make it work. If you can implement your own static file server then do it. If you can't, then it should be a sign that maybe it's not a good idea. Update: See below for solutions without Express.
Problems
Just by glancing at your code code I already see several serious problems with it, including:
Your code is insecure - it allows anyone to get any file on your system.
Your code is blocking - it will grind to a halt as soon as you get any concurrent connections.
Your code doesn't work for binary files - only for text files, and only those with UTF-8 encoding
Your code doesn't work for uppercase filenames, .jpeg extension etc.
Your code doesn't serve HTML files correctly
Your code crashes when files don't exist instead of responding with proper code
Solution
Anyone who answers a question like this has two options: either put a lot of effort and time into fixing every one of the problems mentioned above (which rarely happens because it is not a trivial task and that's why all you see are comments mentioning one or two of those problems instead of answers) or you can explain how the task should be done properly instead of adding countless fixes to something that was not a good idea in the first place.
That having been said, what you can do to achieve your goal here in a secure and performant way is to put your static files (HTML, CSS, images etc.) into a directory, e.g. called html and use Express (or some other frameworks, see below) with a simple code like this:
var path = require('path');
var express = require('express');
var app = express();
var htmlPath = path.join(__dirname, 'html');
app.use(express.static(htmlPath));
var server = app.listen(80, function () {
console.log('listening on port', server.address().port);
});
See the full example with explanation on GitHub:
https://github.com/rsp/node-express-static-example
I put this example on GitHub because there are a lot of questions on Stack Overflow related to problems that people have with serving static files in Node. It's open-source, you can adapt it to your own needs and use in your code.
For more info on Express, see:
http://expressjs.com/en/4x/api.html
Other options
Other frameworks that you can use to serve static files include:
koa, Restify, Hapi, Sails, LoopBack and more.
Without a framework
If you still think that you don't want to use a high-level framework that does the job correctly and you want to roll your own solution, maybe for educational purposes, then see this answer:
How to serve an image using nodejs
It explains how to serve static images with:
express.static (express built-in middleware, like in this answer)
express (express but without express.static)
connect (one level below than express)
http (using Node's http module)
net (not even using http module)
All of the examples posted are tested and work on Node versions 4, 5, 6 and 7.
Other related answers:
How to serve an image using nodejs
Failed to load resource from same directory when redirecting Javascript
onload js call not working with node
Sending whole folder content to client with express
Loading partials fails on the server JS

Related

Serving external resources in Angular 11

I am currently building a gallery app using Angular 11 + Electron + Java, but I came across this issue that I have not managed to solve.
Using the backend, I get all the files within a folder the user chooses, but then, when i use the paths as src for , Angular adds http://localhost:4200 before the path.
I can't use the asset folder because the source path of the folder containing the images is chosen by the user and may vary across different PCs.
What is the proper way to deal with this?
I have found a solution.
First thing is to set
webSecurity: false
in electron's main.ts file.
Then, in the same file, register the following protocol:
app.on('ready', () => {
setTimeout(createWindow, 400);
protocol.registerFileProtocol('file', (request, callback) => {
const pathname = decodeURIComponent(request.url.replace('file:///', ''));
callback(pathname);
});
});
Finally, when using the image path, add file:// before the absolute path of the image.
This carries potential security issues, so carefully evaluate how your app is going to be used!

With express.js, what is the best way for images to load fast?

Just want to ask, I am making an Image Generation Website and it uses node-canvas to create generate the images. Some endpoints use superagent to request (GET) other APIs and display the data on the image.
Currently, I don't have anything for the images to generate and load faster. It uses up a fair bit of my Memory and CPU on my project and can be a big problem for me if I don't implement this. I've looked up something about Redis for caching but I am using Glitch for developing it and it isn't supported there.
I've used the following express.js code after reading a guide on Server Side Caching.
In my image generation file: (e.g. blur.js)
res.header('Cache-Control', 'max-age=120');
One of my Router Files:
const serveStatic = require('serve-static')
router.use(serveStatic(path.join(__dirname, 'public'), {
maxAge: '60',
setHeaders: setCustomCacheControl
function setCustomCacheControl (res, path) {
if (serveStatic.mime.lookup(path) === 'text/html' && "text/javascript") {
// Custom Cache-Control for HTML files
res.setHeader('Cache-Control', 'public, max-age=60')
console.log('Test')
}
}
}))
I've tested the code above and it seemed to be it but I am not 100% certain its working (I even checked the Chrome Console for ms load differences). Well, if I add something like that, it will help benefit my Service that does image generation, JSON and Image Game Statistics Cards as it does not need to be requested over and over again and use a lot of Resources.

Can't view new files in meteors public directory

When a meteor app gets compiled (meteor build app), the public directory becomes \programs\web.browser\app All files which were in the development public directory \public are now accessible with http://domain.tld/file-in-public-directory.jpg
When I put a new file into the compiled public directory and try to view it in the browser, I get an error, which says that Meteor does not have a route for that url. When I do this in the development public directory it works flawless, but not in the compiled (meteor build app).
I need this, because I want to upload new files in that directory.
Any help?
So, you'll have to tweak it a little bit, but there's a way you can access pretty much any folder you want, especially for static files, by using the low level connectHandlers object.
Here is an example where you have a folder named .images (hidden from the Meteor auto-refresh), which serves images whenever a request is made to http://[yoursiteURL]/images/...
var fs = Npm.require('fs');
WebApp.connectHandlers.use(function(req, res, next) {
var re = /^\/images\/(.*)$/.exec(req.url);
if (re !== null) {
var filePath = process.env.PWD
+ '/.images/'
+ re[1];
var data = fs.readFileSync(filePath, data);
res.writeHead(200, {
'Content-Type': 'image'
});
res.write(data);
res.end();
} else {
next();
}
});
You're using a regular expression to find out if the incoming request is trying to access /images/. If it is, we're going to send the image with the appropriate headers, using res.write()
Two things of note:
1- you don't have to use anything special (no packages, etc) to use the Npm.require('fs') because it's built in and usable.
2- using fs.readFileSync is a bit of a hack, and is blocking. You'll want to tweak that for a performant, production app.
Hope this helps! A bit more information on connectHandlers can be found here.
Nice to see folks out there trying meteor. It's great stuff - but at the same time, it does seem complicated. What really helped me so much is using this app: metoer-kitchen. I now use it alongside when working on my projects.

Joining together nodejs html5 and canvas

I've got a very simple html5 game on one side. Opening the game's html file directly with my browser makes the game work just fine. On the other side, I have an html sever made with node.js that can serve html text normally (tags like < /br> < p> and so on).
But when I tell the server to display my game as html text priting the whole html file, the canvas fails to render (although the title does). So now I'm kind of lost on what's happening and why I'm not able to link those two things together. Here's a simplified version of my server's code:
var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(index);
res.end()
}).listen(7777);
So, what am I doing wrong here? Should this work normally? Am I missing something?
It seems just as if the javascript was sent as plain text and the code was never actually executed.
Your server serves only the index.html so if that page depends on any other resources it will fail to work as requests to CSS and JS files will fail. Try out e.g. this:
$ npm -g install simplehttpserver
$ simplehttpserver /path/to/your/folder
Then go with browser to
http://localhost:8000/index.html

How would I create a .js file that contains all of my .html templates in Express & Node.js?

I am using jquery templates on both the server-side and client-side. I'm using the jqtpl and express modules on Node.js for the server, and I have jquery and its template plugin for the client.
Wherever possible the client recieves JSON instead of html, and builds the template itself, using the HTML5 history api to change url and allow session navigation. If this isn't possible, the server does the templating instead and sends html.
Both the server and the client have the exact same templates, but the server has them in the form of 12 .html files, and the client has them in the form of an object in a .js file.
Each time I change or add a template, I have to alter the client .js file to be the same, which is a bit of a pain.
What I would like to do is have the .js file dynamically take all of the .html files in my templates folder and compile them into an object. Once I had finished development, this file would be cached, as it no longer needs to look for changes.
Not sure if this answers your question, but if you're interested in having the same templating code on both client and server, you should take a look at weld which would allow you to use the same code on both client and server.
Could you be a bit more clear about what you're doing with regards to the 12 html files vs 1 object on the client?
Code samples would rock, if possible.
What I was looking for was Node's file system module:
http://nodejs.org/docs/v0.4.8/api/fs.html
I used fs.readdir to find all of the template files in the folder, then iterated through the array that produced to read all of its containing files.
var templates = {};
fs.readdir("./templates", function(err, files) {
for(var i = 0, len = files.length; i<len; i++) {
fs.readFile("./templates/" + files[i], function (err, data) {
if (err) {
throw err
}
templates[files[i]] = data;
});
}
}
And then in express:
app.get("/templates.js", function(req, res){
res.header("Content-Type", "text/javascript");
res.end("var templates = { " + JSON.stringify(templates) + " }; ");
});
However, I found that server-side templating was better suited to my needs, and where appropriate, I now send rendered HTML in my JSON responses instead of just data.

Categories

Resources