]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/blame - src/files.js
Use 222 status code to indicate folder listing and use stdout only for data
[perso/Immae/Projets/Nodejs/Surfer.git] / src / files.js
CommitLineData
ca2d3b4d
JZ
1'use strict';
2
3var fs = require('fs'),
4 path = require('path'),
eb83e4da 5 rm = require('del'),
8c3ae071 6 debug = require('debug')('files'),
eaa62184 7 mkdirp = require('mkdirp'),
ca2d3b4d
JZ
8 HttpError = require('connect-lastmile').HttpError,
9 HttpSuccess = require('connect-lastmile').HttpSuccess;
10
8c3ae071
JZ
11var gBasePath;
12
13exports = module.exports = function (basePath) {
14 gBasePath = basePath;
ca2d3b4d 15
8c3ae071
JZ
16 return {
17 get: get,
18 put: put,
19 del: del
20 };
21};
ca2d3b4d
JZ
22
23// http://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js
24function copyFile(source, target, cb) {
25 var cbCalled = false;
26
eaa62184
JZ
27 // ensure directory
28 mkdirp(path.dirname(target), function (error) {
29 if (error) return cb(error);
ca2d3b4d 30
eaa62184
JZ
31 var rd = fs.createReadStream(source);
32 rd.on("error", function(err) {
33 done(err);
34 });
ca2d3b4d 35
eaa62184
JZ
36 var wr = fs.createWriteStream(target);
37 wr.on("error", function(err) {
38 done(err);
39 });
ca2d3b4d 40
eaa62184
JZ
41 wr.on("close", function(ex) {
42 done();
43 });
44
45 rd.pipe(wr);
ca2d3b4d 46
eaa62184
JZ
47 function done(err) {
48 if (!cbCalled) {
49 cb(err);
50 cbCalled = true;
51 }
ca2d3b4d 52 }
eaa62184 53 });
ca2d3b4d
JZ
54}
55
ca2d3b4d 56function getAbsolutePath(filePath) {
7bb99aff 57 var absoluteFilePath = path.resolve(path.join(gBasePath, filePath));
ca2d3b4d 58
8c3ae071 59 if (absoluteFilePath.indexOf(gBasePath) !== 0) return null;
ca2d3b4d
JZ
60 return absoluteFilePath;
61}
62
63function get(req, res, next) {
64 var filePath = req.params[0];
65 var absoluteFilePath = getAbsolutePath(filePath);
66 if (!absoluteFilePath) return next(new HttpError(403, 'Path not allowed'));
67
68 fs.stat(absoluteFilePath, function (error, result) {
69 if (error) return next(new HttpError(404, error));
70
8c3ae071 71 debug('get', absoluteFilePath);
ca2d3b4d 72
cfe24a27 73 if (result.isFile()) return res.sendFile(absoluteFilePath);
7bb99aff 74 if (result.isDirectory()) return res.status(222).send({ entries: fs.readdirSync(absoluteFilePath) });
ca2d3b4d
JZ
75
76 return next(new HttpError(500, 'unsupported type'));
77 });
78}
79
80function put(req, res, next) {
81 var filePath = req.params[0];
82
83 if (!req.files.file) return next(new HttpError(400, 'missing file'));
84
85 var absoluteFilePath = getAbsolutePath(filePath);
86 if (!absoluteFilePath) return next(new HttpError(403, 'Path not allowed'));
87
88 fs.stat(absoluteFilePath, function (error, result) {
89 if (error && error.code !== 'ENOENT') return next(new HttpError(500, error));
90
8c3ae071 91 debug('put', absoluteFilePath, req.files.file);
ca2d3b4d
JZ
92
93 if (result && result.isDirectory()) return next(new HttpError(409, 'cannot put on directories'));
94 if (!result || result.isFile()) {
95 return copyFile(req.files.file.path, absoluteFilePath, function (error) {
96 if (error) return next(new HttpError(500, error));
97 next(new HttpSuccess(201, {}));
98 });
99 }
100
101 return next(new HttpError(500, 'unsupported type'));
102 });
103}
104
105function del(req, res, next) {
106 var filePath = req.params[0];
107 var absoluteFilePath = getAbsolutePath(filePath);
eaa62184 108 if (!absoluteFilePath) return next(new HttpError(404, 'Not found'));
8c3ae071 109 if (absoluteFilePath.slice(gBasePath.length) === '') return next(new HttpError(403, 'Forbidden'));
ca2d3b4d
JZ
110
111 fs.stat(absoluteFilePath, function (error, result) {
112 if (error) return next(new HttpError(404, error));
113
eb83e4da 114 rm(absoluteFilePath, function (error, result) {
ca2d3b4d 115 if (error) return next(new HttpError(500, 'Unable to remove'));
eb83e4da 116 next(new HttpSuccess(200, { entries: result }));
ca2d3b4d
JZ
117 });
118 });
119}