]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/blob - 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
1 'use strict';
2
3 var fs = require('fs'),
4 path = require('path'),
5 rm = require('del'),
6 debug = require('debug')('files'),
7 mkdirp = require('mkdirp'),
8 HttpError = require('connect-lastmile').HttpError,
9 HttpSuccess = require('connect-lastmile').HttpSuccess;
10
11 var gBasePath;
12
13 exports = module.exports = function (basePath) {
14 gBasePath = basePath;
15
16 return {
17 get: get,
18 put: put,
19 del: del
20 };
21 };
22
23 // http://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js
24 function copyFile(source, target, cb) {
25 var cbCalled = false;
26
27 // ensure directory
28 mkdirp(path.dirname(target), function (error) {
29 if (error) return cb(error);
30
31 var rd = fs.createReadStream(source);
32 rd.on("error", function(err) {
33 done(err);
34 });
35
36 var wr = fs.createWriteStream(target);
37 wr.on("error", function(err) {
38 done(err);
39 });
40
41 wr.on("close", function(ex) {
42 done();
43 });
44
45 rd.pipe(wr);
46
47 function done(err) {
48 if (!cbCalled) {
49 cb(err);
50 cbCalled = true;
51 }
52 }
53 });
54 }
55
56 function getAbsolutePath(filePath) {
57 var absoluteFilePath = path.resolve(path.join(gBasePath, filePath));
58
59 if (absoluteFilePath.indexOf(gBasePath) !== 0) return null;
60 return absoluteFilePath;
61 }
62
63 function 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
71 debug('get', absoluteFilePath);
72
73 if (result.isFile()) return res.sendFile(absoluteFilePath);
74 if (result.isDirectory()) return res.status(222).send({ entries: fs.readdirSync(absoluteFilePath) });
75
76 return next(new HttpError(500, 'unsupported type'));
77 });
78 }
79
80 function 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
91 debug('put', absoluteFilePath, req.files.file);
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
105 function del(req, res, next) {
106 var filePath = req.params[0];
107 var absoluteFilePath = getAbsolutePath(filePath);
108 if (!absoluteFilePath) return next(new HttpError(404, 'Not found'));
109 if (absoluteFilePath.slice(gBasePath.length) === '') return next(new HttpError(403, 'Forbidden'));
110
111 fs.stat(absoluteFilePath, function (error, result) {
112 if (error) return next(new HttpError(404, error));
113
114 rm(absoluteFilePath, function (error, result) {
115 if (error) return next(new HttpError(500, 'Unable to remove'));
116 next(new HttpSuccess(200, { entries: result }));
117 });
118 });
119 }