summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--matweb/oas/remove_metadata.yml41
-rw-r--r--matweb/rest_api.py36
-rw-r--r--test/test_api.py63
3 files changed, 137 insertions, 3 deletions
diff --git a/matweb/oas/remove_metadata.yml b/matweb/oas/remove_metadata.yml
new file mode 100644
index 0000000..ad5a7da
--- /dev/null
+++ b/matweb/oas/remove_metadata.yml
@@ -0,0 +1,41 @@
1---
2tags:
3 - "Metadata removal cleaning in one request (automated clients)"
4summary: 'Upload a single file which will be cleaned from metadata and returned directly'
5requestBody:
6 description: "The file that will be cleaned from metadata and the cleaned file is returned directly"
7 required: true
8 content:
9 multipart/form-data:
10 schema:
11 type: object
12 properties:
13 file:
14 type: string
15 format: binary
16responses:
17 '200':
18 description: "The cleaned file"
19 content:
20 "*/*":
21 schema:
22 type: string
23 format: binary
24 400:
25 description: "Invalid input"
26 content:
27 application/json:
28 schema:
29 $ref: '#/components/schemas/ErrorResponse'
30 415:
31 description: "Unsupported file type"
32 content:
33 application/json:
34 schema:
35 $ref: '#/components/schemas/ErrorResponse'
36 500:
37 description: "Unable to clean the file"
38 content:
39 application/json:
40 schema:
41 $ref: '#/components/schemas/ErrorResponse' \ No newline at end of file
diff --git a/matweb/rest_api.py b/matweb/rest_api.py
index 2909cf6..50b7c37 100644
--- a/matweb/rest_api.py
+++ b/matweb/rest_api.py
@@ -84,6 +84,38 @@ class APIDownload(Resource):
84 return send_from_directory(current_app.config['UPLOAD_FOLDER'], filepath, as_attachment=True) 84 return send_from_directory(current_app.config['UPLOAD_FOLDER'], filepath, as_attachment=True)
85 85
86 86
87class APIClean(Resource):
88 @swag_from('./oas/remove_metadata.yml')
89 def post(self):
90 if 'file' not in request.files:
91 abort(400, message='No file part')
92
93 uploaded_file = request.files['file']
94 if not uploaded_file.filename:
95 abort(400, message='No selected `file`')
96 try:
97 filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER'])
98 except ValueError:
99 abort(400, message='Invalid Filename')
100
101 parser, mime = utils.get_file_parser(filepath)
102
103 if parser is None:
104 abort(415, message='The type %s is not supported' % mime)
105
106 if parser.remove_all() is not True:
107 abort(500, message='Unable to clean %s' % mime)
108
109 _, _, _, output_filename = utils.cleanup(parser, filepath, current_app.config['UPLOAD_FOLDER'])
110
111 @after_this_request
112 def remove_file(response):
113 os.remove(os.path.join(current_app.config['UPLOAD_FOLDER'], output_filename))
114 return response
115
116 return send_from_directory(current_app.config['UPLOAD_FOLDER'], output_filename, as_attachment=True)
117
118
87class APIBulkDownloadCreator(Resource): 119class APIBulkDownloadCreator(Resource):
88 schema = { 120 schema = {
89 'download_list': { 121 'download_list': {
@@ -169,6 +201,10 @@ api.add_resource(
169 '/download/<string:key>/<string:secret>/<string:filename>' 201 '/download/<string:key>/<string:secret>/<string:filename>'
170) 202)
171api.add_resource( 203api.add_resource(
204 APIClean,
205 '/remove_metadata'
206)
207api.add_resource(
172 APIBulkDownloadCreator, 208 APIBulkDownloadCreator,
173 '/download/bulk' 209 '/download/bulk'
174) 210)
diff --git a/test/test_api.py b/test/test_api.py
index 6961197..6d48a35 100644
--- a/test/test_api.py
+++ b/test/test_api.py
@@ -1,13 +1,15 @@
1import unittest
2import tempfile
3import json 1import json
4import os 2import os
5import shutil 3import shutil
4import tempfile
5import unittest
6import zipfile 6import zipfile
7from six import BytesIO 7import io
8 8
9from unittest.mock import patch 9from unittest.mock import patch
10
10from openapi_spec_validator import validate_spec 11from openapi_spec_validator import validate_spec
12from six import BytesIO
11 13
12import main 14import main
13 15
@@ -433,5 +435,60 @@ class Mat2APITestCase(unittest.TestCase):
433 spec = self.app.get('apispec_1.json').get_json() 435 spec = self.app.get('apispec_1.json').get_json()
434 validate_spec(spec) 436 validate_spec(spec)
435 437
438 def test_remove_metadata(self):
439 r = self.app.post(
440 '/api/remove_metadata',
441 data=dict(
442 file=(io.BytesIO(b""), 'test.txt'),
443 ),
444 follow_redirects=False
445 )
446 self.assertEqual(r.status_code, 200)
447 self.assertEqual(r.headers['Content-Disposition'], 'attachment; filename=test.cleaned.txt')
448 self.assertEqual(r.headers['Content-Type'], 'text/plain; charset=utf-8')
449 self.assertEqual(r.data, b'')
450
451 def test_remove_metdata_validation(self):
452 r = self.app.post(
453 '/api/remove_metadata',
454 data=dict(
455 fileNotExisting=(io.BytesIO(b""), 'test.random'),
456 ),
457 follow_redirects=False
458 )
459 self.assertEqual(r.get_json()['message'], 'No file part')
460 self.assertEqual(r.status_code, 400)
461
462 r = self.app.post(
463 '/api/remove_metadata',
464 data=dict(
465 file=(io.BytesIO(b""), ''),
466 ),
467 follow_redirects=False
468 )
469 self.assertEqual(r.get_json()['message'], 'No selected `file`')
470 self.assertEqual(r.status_code, 400)
471
472 r = self.app.post(
473 '/api/remove_metadata',
474 data=dict(
475 file=(io.BytesIO(b""), '../../'),
476 ),
477 follow_redirects=False
478 )
479 self.assertEqual(r.get_json()['message'], 'Invalid Filename')
480 self.assertEqual(r.status_code, 400)
481
482 r = self.app.post(
483 '/api/remove_metadata',
484 data=dict(
485 file=(io.BytesIO(b""), 'test.random'),
486 ),
487 follow_redirects=False
488 )
489 self.assertEqual(r.get_json()['message'], 'The type None is not supported')
490 self.assertEqual(r.status_code, 415)
491
492
436if __name__ == '__main__': 493if __name__ == '__main__':
437 unittest.main() 494 unittest.main()