impelement http api
This commit is contained in:
parent
bc8e58e472
commit
65d4779083
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
data
|
data
|
||||||
|
*.code-workspace
|
||||||
|
.vscode
|
||||||
145
index.js
145
index.js
@ -1,25 +1,25 @@
|
|||||||
const express = require('express')
|
const express = require('express');
|
||||||
const fileUpload = require('express-fileupload')
|
const fileUpload = require('express-fileupload');
|
||||||
const app = express()
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const port = 3000
|
const mime = require( 'mime' );
|
||||||
|
const app = express();
|
||||||
|
const port = 3000;
|
||||||
|
|
||||||
const uploadPath = process.env.UPLOAD_PATH || '/tmp';
|
const uploadPath = process.env.UPLOAD_PATH || '/tmp';
|
||||||
const config = process.env.config || '{ "uploadGroups": [{ "matcher": "^test.*\.txt$", "groupSize": 3}] } ';
|
const config = process.env.config || '{ "uploadGroups": [{ "matcher": "^test.*\.txt$", "groupSize": 3}] }';
|
||||||
|
|
||||||
app.use(fileUpload())
|
app.use(fileUpload());
|
||||||
|
|
||||||
app.use((req, res, next) =>{
|
app.use((req, res, next) => {
|
||||||
const authenticated = req.get('Authorization') === 'Bearer ' + process.env.API_KEY ;
|
const authenticated = req.get('Authorization') === 'Bearer ' + process.env.API_KEY;
|
||||||
if(!authenticated){
|
if (!authenticated) {
|
||||||
return res.status(401).send('Unauthorized');
|
return res.status(401).send('Unauthorized');
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const processGroups = () => {
|
const processGroups = () => {
|
||||||
const files = [] = fs.readdirSync(uploadPath);
|
const files = fs.readdirSync(uploadPath);
|
||||||
|
|
||||||
// Sort files by modification time (mtime)
|
// Sort files by modification time (mtime)
|
||||||
files.sort((a, b) => {
|
files.sort((a, b) => {
|
||||||
@ -32,29 +32,65 @@ const processGroups = () => {
|
|||||||
|
|
||||||
// collection files for defined groups
|
// collection files for defined groups
|
||||||
JSON.parse(config).uploadGroups.forEach(group => {
|
JSON.parse(config).uploadGroups.forEach(group => {
|
||||||
//const filesStartingWithPrefix = files.filter(file => new RegExp(group.mathcer).test(file));
|
|
||||||
const filesStartingWithPrefix = files.filter(file => new RegExp(group.matcher).test(file));
|
const filesStartingWithPrefix = files.filter(file => new RegExp(group.matcher).test(file));
|
||||||
groups.push({ ...group, files: filesStartingWithPrefix })
|
groups.push({ ...group, files: filesStartingWithPrefix });
|
||||||
});
|
});
|
||||||
return groups;
|
return groups;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* clean up files based on the group size
|
||||||
|
*/
|
||||||
const cleanUp = () => {
|
const cleanUp = () => {
|
||||||
|
|
||||||
const groups = processGroups();
|
const groups = processGroups();
|
||||||
|
|
||||||
groups.forEach(group => {
|
groups.forEach(group => {
|
||||||
if (group.files.length > group.groupSize) {
|
if (group.files.length > group.groupSize) {
|
||||||
const filesToDelete = group.files.slice(0, group.files.length - group.groupSize);
|
const filesToDelete = group.files.slice(0, group.files.length - group.groupSize);
|
||||||
filesToDelete.forEach(file => {
|
filesToDelete.forEach(file => {
|
||||||
console.log(new Date().toISOString() +" Deleting file: ", file);
|
console.log(new Date().toISOString() + " Deleting file: ", file);
|
||||||
fs.unlinkSync(uploadPath + "/" + file);
|
fs.unlinkSync(uploadPath + "/" + file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
*
|
||||||
|
* upload a file
|
||||||
|
* throws 400 if no file was uploaded
|
||||||
|
* throws 409 if file already exists and overwrite is false
|
||||||
|
* throws 500 if file upload failed
|
||||||
|
*/
|
||||||
|
const uploadFile = (req, res, overwrite) => {
|
||||||
|
let sampleFile;
|
||||||
|
|
||||||
|
const uploadedFileKeys = Object.keys(req.files);
|
||||||
|
if (!req.files || uploadedFileKeys.length === 0) {
|
||||||
|
return res.status(400).send('No files were uploaded.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let messages = "";
|
||||||
|
|
||||||
|
const uploadedFileObj = req.files[uploadedFileKeys[0]];
|
||||||
|
let uploadFilePath = uploadPath + "/" + uploadedFileObj.name;
|
||||||
|
|
||||||
|
if (fs.existsSync(uploadFilePath) && !overwrite) {
|
||||||
|
console.log(new Date().toISOString() + " File already exists: ", uploadFilePath);
|
||||||
|
return res.status(409).send('File already exists.');
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadedFileObj.mv(uploadFilePath, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log(new Date().toISOString() + " File upalod failed: ", err);
|
||||||
|
return res.status(500).send(err);
|
||||||
|
}
|
||||||
|
console.log(new Date().toISOString() + " File uploaded to: ", uploadFilePath);
|
||||||
|
cleanUp();
|
||||||
|
res.send('File(s) uploaded!');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
app.get('/state', (req, res) => {
|
app.get('/state', (req, res) => {
|
||||||
const groups = processGroups();
|
const groups = processGroups();
|
||||||
@ -77,32 +113,59 @@ app.get('/', (req, res) => {
|
|||||||
res.send(files);
|
res.send(files);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/*', function (req, res) {
|
/**
|
||||||
let sampleFile;
|
*
|
||||||
|
* upload a file
|
||||||
const uploadedFileKeys = Object.keys(req.files);
|
* throws 409 if file already exists
|
||||||
if (!req.files || uploadedFileKeys.length === 0) {
|
*/
|
||||||
return res.status(400).send('No files were uploaded.');
|
app.post('/', function (req, res) {
|
||||||
}
|
uploadFile(req, res, false);
|
||||||
|
|
||||||
let messages = "";
|
|
||||||
|
|
||||||
const uploadedFileObj = req.files[uploadedFileKeys[0]];
|
|
||||||
let uploadFilePath = uploadPath + "/" + uploadedFileObj.name;
|
|
||||||
|
|
||||||
uploadedFileObj.mv(uploadFilePath, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return res.status(500).send(err);
|
|
||||||
}
|
|
||||||
console.log( new Date().toISOString() +" File uploaded to: ", uploadFilePath);
|
|
||||||
cleanUp();
|
|
||||||
res.send('File(s) uploaded!');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* upload or replace a file
|
||||||
|
*/
|
||||||
|
app.put('/', function (req, res) {
|
||||||
|
uploadFile(req, res, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* delete a file with the given filename
|
||||||
|
* throws 404 if file not found
|
||||||
|
*/
|
||||||
|
app.delete('/:filename', (req, res) => {
|
||||||
|
const filename = req.params.filename;
|
||||||
|
const filePath = uploadPath + "/" + filename;
|
||||||
|
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
res.send(`File ${filename} deleted!`);
|
||||||
|
} else {
|
||||||
|
res.status(404).send('File not found.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* get a file with the given filename
|
||||||
|
* returns the file content with the appropriate Content-Type
|
||||||
|
*/
|
||||||
|
app.get('/:filename', (req, res) => {
|
||||||
|
const filename = req.params.filename;
|
||||||
|
const filePath = uploadPath + "/" + filename;
|
||||||
|
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
// todo: mime.getType is not a function
|
||||||
|
//const mimeType = mime.getType(filePath);
|
||||||
|
//res.setHeader('Content-Type', mimeType);
|
||||||
|
fs.createReadStream(filePath).pipe(res);
|
||||||
|
} else {
|
||||||
|
res.status(404).send('File not found.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Example app listening on port ${port}`)
|
console.log(`Example app listening on port ${port}`);
|
||||||
})
|
});
|
||||||
28
package-lock.json
generated
28
package-lock.json
generated
@ -10,7 +10,8 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"express-fileupload": "^1.5.1"
|
"express-fileupload": "^1.5.1",
|
||||||
|
"mime": "^4.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
@ -498,15 +499,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mime": {
|
"node_modules/mime": {
|
||||||
"version": "1.6.0",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-4.0.6.tgz",
|
||||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
"integrity": "sha512-4rGt7rvQHBbaSOF9POGkk1ocRP16Md1x36Xma8sz8h8/vfCUI2OtEIeCqe4Ofes853x4xDoPiFLIT47J5fI/7A==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"mime": "cli.js"
|
"mime": "bin/cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mime-db": {
|
"node_modules/mime-db": {
|
||||||
@ -695,6 +699,18 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/send/node_modules/mime": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/send/node_modules/ms": {
|
"node_modules/send/node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"express-fileupload": "^1.5.1"
|
"express-fileupload": "^1.5.1",
|
||||||
|
"mime": "^4.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user