Refactor files.js into FilesController.
This commit is contained in:
97
src/Controllers/FilesController.js
Normal file
97
src/Controllers/FilesController.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// FilesController.js
|
||||||
|
|
||||||
|
import express from 'express';
|
||||||
|
import mime from 'mime';
|
||||||
|
import { Parse } from 'parse/node';
|
||||||
|
import BodyParser from 'body-parser';
|
||||||
|
import hat from 'hat';
|
||||||
|
import * as Middlewares from '../middlewares';
|
||||||
|
import Config from '../Config';
|
||||||
|
|
||||||
|
const rack = hat.rack();
|
||||||
|
|
||||||
|
export class FilesController {
|
||||||
|
constructor(filesAdapter) {
|
||||||
|
this._filesAdapter = filesAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler() {
|
||||||
|
return (req, res) => {
|
||||||
|
let config = new Config(req.params.appId);
|
||||||
|
this._filesAdapter.getFileDataAsync(config, req.params.filename).then((data) => {
|
||||||
|
res.status(200);
|
||||||
|
var contentType = mime.lookup(req.params.filename);
|
||||||
|
res.set('Content-type', contentType);
|
||||||
|
res.end(data);
|
||||||
|
}).catch((error) => {
|
||||||
|
res.status(404);
|
||||||
|
res.set('Content-type', 'text/plain');
|
||||||
|
res.end('File not found.');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
createHandler() {
|
||||||
|
return (req, res, next) => {
|
||||||
|
if (!req.body || !req.body.length) {
|
||||||
|
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
||||||
|
'Invalid file upload.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.params.filename.length > 128) {
|
||||||
|
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
||||||
|
'Filename too long.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req.params.filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) {
|
||||||
|
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
||||||
|
'Filename contains invalid characters.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a content-type is included, we'll add an extension so we can
|
||||||
|
// return the same content-type.
|
||||||
|
let extension = '';
|
||||||
|
let hasExtension = req.params.filename.indexOf('.') > 0;
|
||||||
|
let contentType = req.get('Content-type');
|
||||||
|
if (!hasExtension && contentType && mime.extension(contentType)) {
|
||||||
|
extension = '.' + mime.extension(contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = rack() + '_' + req.params.filename + extension;
|
||||||
|
this._filesAdapter.createFileAsync(req.config, filename, req.body).then(() => {
|
||||||
|
res.status(201);
|
||||||
|
var location = this._filesAdapter.getFileLocation(req.config, req, filename);
|
||||||
|
res.set('Location', location);
|
||||||
|
res.json({ url: location, name: filename });
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
||||||
|
'Could not store file.'));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getExpressRouter() {
|
||||||
|
let router = express.Router();
|
||||||
|
router.get('/files/:appId/:filename', this.getHandler());
|
||||||
|
|
||||||
|
router.post('/files', function(req, res, next) {
|
||||||
|
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
||||||
|
'Filename not provided.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/files/:filename',
|
||||||
|
Middlewares.allowCrossDomain,
|
||||||
|
BodyParser.raw({type: '*/*', limit: '20mb'}),
|
||||||
|
Middlewares.handleParseHeaders,
|
||||||
|
this.createHandler()
|
||||||
|
);
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilesController;
|
||||||
@@ -11,16 +11,6 @@
|
|||||||
// and for the API server to be using the ExportAdapter
|
// and for the API server to be using the ExportAdapter
|
||||||
// database adapter.
|
// database adapter.
|
||||||
|
|
||||||
let adapter = null;
|
|
||||||
|
|
||||||
export function setAdapter(filesAdapter) {
|
|
||||||
adapter = filesAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAdapter() {
|
|
||||||
return adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FilesAdapter {
|
export class FilesAdapter {
|
||||||
createFileAsync(config, filename, data) { }
|
createFileAsync(config, filename, data) { }
|
||||||
|
|
||||||
@@ -28,3 +18,5 @@ export class FilesAdapter {
|
|||||||
|
|
||||||
getFileLocation(config, request, filename) { }
|
getFileLocation(config, request, filename) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default FilesAdapter;
|
||||||
|
|||||||
85
src/files.js
85
src/files.js
@@ -1,85 +0,0 @@
|
|||||||
// files.js
|
|
||||||
|
|
||||||
var bodyParser = require('body-parser'),
|
|
||||||
Config = require('./Config'),
|
|
||||||
express = require('express'),
|
|
||||||
middlewares = require('./middlewares.js'),
|
|
||||||
mime = require('mime'),
|
|
||||||
Parse = require('parse/node').Parse,
|
|
||||||
rack = require('hat').rack();
|
|
||||||
|
|
||||||
import { getAdapter as getFilesAdapter } from './FilesAdapter';
|
|
||||||
|
|
||||||
var router = express.Router();
|
|
||||||
|
|
||||||
var processCreate = function(req, res, next) {
|
|
||||||
if (!req.body || !req.body.length) {
|
|
||||||
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
|
||||||
'Invalid file upload.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.params.filename.length > 128) {
|
|
||||||
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
|
||||||
'Filename too long.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!req.params.filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) {
|
|
||||||
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
|
||||||
'Filename contains invalid characters.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a content-type is included, we'll add an extension so we can
|
|
||||||
// return the same content-type.
|
|
||||||
var extension = '';
|
|
||||||
var hasExtension = req.params.filename.indexOf('.') > 0;
|
|
||||||
var contentType = req.get('Content-type');
|
|
||||||
if (!hasExtension && contentType && mime.extension(contentType)) {
|
|
||||||
extension = '.' + mime.extension(contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
var filename = rack() + '_' + req.params.filename + extension;
|
|
||||||
getFilesAdapter().createFileAsync(req.config, filename, req.body).then(() => {
|
|
||||||
res.status(201);
|
|
||||||
var location = getFilesAdapter().getFileLocation(req.config, req, filename);
|
|
||||||
res.set('Location', location);
|
|
||||||
res.json({ url: location, name: filename });
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
next(new Parse.Error(Parse.Error.FILE_SAVE_ERROR,
|
|
||||||
'Could not store file.'));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var processGet = function(req, res) {
|
|
||||||
var config = new Config(req.params.appId);
|
|
||||||
getFilesAdapter().getFileDataAsync(config, req.params.filename).then((data) => {
|
|
||||||
res.status(200);
|
|
||||||
var contentType = mime.lookup(req.params.filename);
|
|
||||||
res.set('Content-type', contentType);
|
|
||||||
res.end(data);
|
|
||||||
}).catch((error) => {
|
|
||||||
res.status(404);
|
|
||||||
res.set('Content-type', 'text/plain');
|
|
||||||
res.end('File not found.');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
router.get('/files/:appId/:filename', processGet);
|
|
||||||
|
|
||||||
router.post('/files', function(req, res, next) {
|
|
||||||
next(new Parse.Error(Parse.Error.INVALID_FILE_NAME,
|
|
||||||
'Filename not provided.'));
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/files/:filename',
|
|
||||||
middlewares.allowCrossDomain,
|
|
||||||
bodyParser.raw({type: '*/*', limit: '20mb'}),
|
|
||||||
middlewares.handleParseHeaders,
|
|
||||||
processCreate);
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
router: router
|
|
||||||
};
|
|
||||||
13
src/index.js
13
src/index.js
@@ -12,8 +12,8 @@ var batch = require('./batch'),
|
|||||||
PromiseRouter = require('./PromiseRouter'),
|
PromiseRouter = require('./PromiseRouter'),
|
||||||
httpRequest = require('./httpRequest');
|
httpRequest = require('./httpRequest');
|
||||||
|
|
||||||
import { setAdapter as setFilesAdapter } from './FilesAdapter';
|
|
||||||
import { default as GridStoreAdapter } from './GridStoreAdapter';
|
import { default as GridStoreAdapter } from './GridStoreAdapter';
|
||||||
|
import { default as FilesController } from './Controllers/FilesController';
|
||||||
|
|
||||||
// Mutate the Parse object to add the Cloud Code handlers
|
// Mutate the Parse object to add the Cloud Code handlers
|
||||||
addParseCloud();
|
addParseCloud();
|
||||||
@@ -48,11 +48,9 @@ function ParseServer(args) {
|
|||||||
if (args.databaseAdapter) {
|
if (args.databaseAdapter) {
|
||||||
DatabaseAdapter.setAdapter(args.databaseAdapter);
|
DatabaseAdapter.setAdapter(args.databaseAdapter);
|
||||||
}
|
}
|
||||||
if (args.filesAdapter) {
|
|
||||||
setFilesAdapter(args.filesAdapter);
|
let filesAdapter = args.filesAdapter || new GridStoreAdapter();
|
||||||
} else {
|
|
||||||
setFilesAdapter(new GridStoreAdapter());
|
|
||||||
}
|
|
||||||
if (args.databaseURI) {
|
if (args.databaseURI) {
|
||||||
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
|
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
|
||||||
}
|
}
|
||||||
@@ -95,7 +93,8 @@ function ParseServer(args) {
|
|||||||
var api = express();
|
var api = express();
|
||||||
|
|
||||||
// File handling needs to be before default middlewares are applied
|
// File handling needs to be before default middlewares are applied
|
||||||
api.use('/', require('./files').router);
|
let filesController = new FilesController(filesAdapter);
|
||||||
|
api.use('/', filesController.getExpressRouter());
|
||||||
|
|
||||||
// TODO: separate this from the regular ParseServer object
|
// TODO: separate this from the regular ParseServer object
|
||||||
if (process.env.TESTING == 1) {
|
if (process.env.TESTING == 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user