J'essaie de créer un serveur de fichiers statique dans nodejs plus comme un exercice pour comprendre le nœud que comme un serveur parfait. Je connais bien des projets comme Connect et node-static et j'ai pleinement l'intention d'utiliser ces bibliothèques pour un code plus prêt pour la production, mais j'aime aussi comprendre les bases de ce avec quoi je travaille. Dans cet esprit, j'ai codé un petit server.js:
var http = require('http'),
url = require('url'),
path = require('path'),
fs = require('fs');
var mimeTypes = {
"html": "text/html",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"png": "image/png",
"js": "text/javascript",
"css": "text/css"};
http.createServer(function(req, res) {
var uri = url.parse(req.url).pathname;
var filename = path.join(process.cwd(), uri);
path.exists(filename, function(exists) {
if(!exists) {
console.log("not exists: " + filename);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('404 Not Found\n');
res.end();
}
var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
res.writeHead(200, mimeType);
var fileStream = fs.createReadStream(filename);
fileStream.pipe(res);
}); //end path.exists
}).listen(1337);
Ma question est double
Est-ce la "bonne" façon de créer et de diffuser du code HTML de base, etc.
Le .pipe () dans node fait-il essentiellement ce qui suit?
.
var fileStream = fs.createReadStream(filename);
fileStream.on('data', function (data) {
res.write(data);
});
fileStream.on('end', function() {
res.end();
});
Merci tout le monde!
fs.exists()
plutôt quepath.exists()
dans le code ci-dessus. À votre santé! et ouais! n'oubliez pasreturn
:fs.exists()
est obsolète . Utilisezfs.access()
ou encore mieux que pour le cas d'utilisation ci - dessus,fs.stat()
. 2)url.parse
est obsolète ; utiliseznew URL
plutôt la nouvelle interface.Réponses:
Votre serveur de base a l'air bien, sauf:
Il
return
manque une déclaration.res.write('404 Not Found\n'); res.end(); return; // <- Don't forget to return here !!
Et:
res.writeHead(200, mimeType);
devrait être:
res.writeHead(200, {'Content-Type':mimeType});
Oui
pipe()
fait essentiellement cela, il met également en pause / reprend le flux source (au cas où le récepteur serait plus lent). Voici le code source de lapipe()
fonction: https://github.com/joyent/node/blob/master/lib/stream.jsla source
Moins est plus
Allez simplement à l'invite de commande sur votre projet et utilisez
Ensuite, écrivez votre code app.js comme ceci:
var express = require('express'), app = express(), port = process.env.PORT || 4000; app.use(express.static(__dirname + '/public')); app.listen(port);
Vous créeriez alors un dossier «public» dans lequel vous placez vos fichiers. J'ai d'abord essayé la méthode la plus difficile, mais vous devez vous soucier des types de mime, qui consiste simplement à mapper des éléments qui prennent du temps, puis à vous soucier des types de réponse, etc. etc. etc., non merci.
la source
require('http')
en deuxième ligne?J'aime aussi comprendre ce qui se passe sous le capot.
J'ai remarqué quelques éléments dans votre code que vous souhaitez probablement nettoyer:
Il se bloque lorsque le nom de fichier pointe vers un répertoire, car existe est vrai et il essaie de lire un flux de fichiers. J'ai utilisé fs.lstatSync pour déterminer l'existence du répertoire.
Il n'utilise pas correctement les codes de réponse HTTP (200, 404, etc.)
Pendant que MimeType est déterminé (à partir de l'extension de fichier), il n'est pas défini correctement dans res.writeHead (comme l'a souligné stewe)
Pour gérer les caractères spéciaux, vous voudrez probablement échapper à l'URI
Il suit aveuglément les liens symboliques (pourrait être un problème de sécurité)
Compte tenu de cela, certaines des options apache (FollowSymLinks, ShowIndexes, etc.) commencent à avoir plus de sens. J'ai mis à jour le code de votre serveur de fichiers simple comme suit:
var http = require('http'), url = require('url'), path = require('path'), fs = require('fs'); var mimeTypes = { "html": "text/html", "jpeg": "image/jpeg", "jpg": "image/jpeg", "png": "image/png", "js": "text/javascript", "css": "text/css"}; http.createServer(function(req, res) { var uri = url.parse(req.url).pathname; var filename = path.join(process.cwd(), unescape(uri)); var stats; try { stats = fs.lstatSync(filename); // throws if path doesn't exist } catch (e) { res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('404 Not Found\n'); res.end(); return; } if (stats.isFile()) { // path exists, is a file var mimeType = mimeTypes[path.extname(filename).split(".").reverse()[0]]; res.writeHead(200, {'Content-Type': mimeType} ); var fileStream = fs.createReadStream(filename); fileStream.pipe(res); } else if (stats.isDirectory()) { // path exists, is a directory res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('Index of '+uri+'\n'); res.write('TODO, show index?\n'); res.end(); } else { // Symbolic link, other? // TODO: follow symlinks? security? res.writeHead(500, {'Content-Type': 'text/plain'}); res.write('500 Internal server error\n'); res.end(); } }).listen(1337);
la source
var mimeType = mimeTypes[path.extname(filename).match(/\.([^\.]+)$/)[1]];
var http = require('http') var fs = require('fs') var server = http.createServer(function (req, res) { res.writeHead(200, { 'content-type': 'text/plain' }) fs.createReadStream(process.argv[3]).pipe(res) }) server.listen(Number(process.argv[2]))
la source
Que diriez-vous de ce modèle, qui évite de vérifier séparément que le fichier existe
var fileStream = fs.createReadStream(filename); fileStream.on('error', function (error) { response.writeHead(404, { "Content-Type": "text/plain"}); response.end("file not found"); }); fileStream.on('open', function() { var mimeType = mimeTypes[path.extname(filename).split(".")[1]]; response.writeHead(200, {'Content-Type': mimeType}); }); fileStream.on('end', function() { console.log('sent file ' + filename); }); fileStream.pipe(response);
la source
fileStream.on('open', ...
J'ai créé une fonction httpServer avec des fonctionnalités supplémentaires pour un usage général basé sur la réponse @Jeff Ward
Usage:
https://github.com/kenokabe/ConciseStaticHttpServer
Merci.
la source
le module st facilite la diffusion de fichiers statiques. Voici un extrait de README.md:
var mount = st({ path: __dirname + '/static', url: '/static' }) http.createServer(function(req, res) { var stHandled = mount(req, res); if (stHandled) return else res.end('this is not a static file') }).listen(1338)
la source
La réponse de @JasonSebring m'a orienté dans la bonne direction, mais son code est obsolète. Voici comment procéder avec la dernière
connect
version.var connect = require('connect'), serveStatic = require('serve-static'), serveIndex = require('serve-index'); var app = connect() .use(serveStatic('public')) .use(serveIndex('public', {'icons': true, 'view': 'details'})) .listen(3000);
Dans le
connect
référentiel GitHub, vous pouvez utiliser d'autres middlewares.la source
connect
documentation, ce n'est qu'unwrapper
pourmiddleware
. Tous les autres éléments intéressantsmiddleware
proviennent duexpress
référentiel, vous pouvez donc techniquement utiliser ces API en utilisant leexpress.use()
.