@@ -7,34 +7,33 @@ var batch = require('./batch'),
|
||||
Parse = require('parse/node').Parse,
|
||||
path = require('path');
|
||||
|
||||
import { ParseServerOptions,
|
||||
LiveQueryServerOptions } from './Options';
|
||||
import defaults from './defaults';
|
||||
import * as logging from './logger';
|
||||
import Config from './Config';
|
||||
import PromiseRouter from './PromiseRouter';
|
||||
import requiredParameter from './requiredParameter';
|
||||
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
|
||||
import { ClassesRouter } from './Routers/ClassesRouter';
|
||||
import { FeaturesRouter } from './Routers/FeaturesRouter';
|
||||
import { FilesRouter } from './Routers/FilesRouter';
|
||||
import { FunctionsRouter } from './Routers/FunctionsRouter';
|
||||
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
|
||||
import { HooksRouter } from './Routers/HooksRouter';
|
||||
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
|
||||
import { InstallationsRouter } from './Routers/InstallationsRouter';
|
||||
import { LogsRouter } from './Routers/LogsRouter';
|
||||
import { ParseServerOptions, LiveQueryServerOptions } from './Options';
|
||||
import defaults from './defaults';
|
||||
import * as logging from './logger';
|
||||
import Config from './Config';
|
||||
import PromiseRouter from './PromiseRouter';
|
||||
import requiredParameter from './requiredParameter';
|
||||
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
|
||||
import { ClassesRouter } from './Routers/ClassesRouter';
|
||||
import { FeaturesRouter } from './Routers/FeaturesRouter';
|
||||
import { FilesRouter } from './Routers/FilesRouter';
|
||||
import { FunctionsRouter } from './Routers/FunctionsRouter';
|
||||
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
|
||||
import { HooksRouter } from './Routers/HooksRouter';
|
||||
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
|
||||
import { InstallationsRouter } from './Routers/InstallationsRouter';
|
||||
import { LogsRouter } from './Routers/LogsRouter';
|
||||
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
|
||||
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
|
||||
import { PushRouter } from './Routers/PushRouter';
|
||||
import { CloudCodeRouter } from './Routers/CloudCodeRouter';
|
||||
import { RolesRouter } from './Routers/RolesRouter';
|
||||
import { SchemasRouter } from './Routers/SchemasRouter';
|
||||
import { SessionsRouter } from './Routers/SessionsRouter';
|
||||
import { UsersRouter } from './Routers/UsersRouter';
|
||||
import { PurgeRouter } from './Routers/PurgeRouter';
|
||||
import { AudiencesRouter } from './Routers/AudiencesRouter';
|
||||
import { AggregateRouter } from './Routers/AggregateRouter';
|
||||
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
|
||||
import { PushRouter } from './Routers/PushRouter';
|
||||
import { CloudCodeRouter } from './Routers/CloudCodeRouter';
|
||||
import { RolesRouter } from './Routers/RolesRouter';
|
||||
import { SchemasRouter } from './Routers/SchemasRouter';
|
||||
import { SessionsRouter } from './Routers/SessionsRouter';
|
||||
import { UsersRouter } from './Routers/UsersRouter';
|
||||
import { PurgeRouter } from './Routers/PurgeRouter';
|
||||
import { AudiencesRouter } from './Routers/AudiencesRouter';
|
||||
import { AggregateRouter } from './Routers/AggregateRouter';
|
||||
|
||||
import { ParseServerRESTController } from './ParseServerRESTController';
|
||||
import * as controllers from './Controllers';
|
||||
@@ -72,7 +71,7 @@ class ParseServer {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ParseServerOptions} options the parse server initialization options
|
||||
*/
|
||||
*/
|
||||
constructor(options: ParseServerOptions) {
|
||||
injectDefaults(options);
|
||||
const {
|
||||
@@ -108,7 +107,7 @@ class ParseServer {
|
||||
if (cloud) {
|
||||
addParseCloud();
|
||||
if (typeof cloud === 'function') {
|
||||
cloud(Parse)
|
||||
cloud(Parse);
|
||||
} else if (typeof cloud === 'string') {
|
||||
require(path.resolve(process.cwd(), cloud));
|
||||
} else {
|
||||
@@ -135,25 +134,33 @@ class ParseServer {
|
||||
* @static
|
||||
* Create an express app for the parse server
|
||||
* @param {Object} options let you specify the maxUploadSize when creating the express app */
|
||||
static app({maxUploadSize = '20mb', appId}) {
|
||||
static app({ maxUploadSize = '20mb', appId }) {
|
||||
// This app serves the Parse API directly.
|
||||
// It's the equivalent of https://api.parse.com/1 in the hosted Parse API.
|
||||
var api = express();
|
||||
//api.use("/apps", express.static(__dirname + "/public"));
|
||||
// File handling needs to be before default middlewares are applied
|
||||
api.use('/', middlewares.allowCrossDomain, new FilesRouter().expressRouter({
|
||||
maxUploadSize: maxUploadSize
|
||||
}));
|
||||
api.use(
|
||||
'/',
|
||||
middlewares.allowCrossDomain,
|
||||
new FilesRouter().expressRouter({
|
||||
maxUploadSize: maxUploadSize,
|
||||
})
|
||||
);
|
||||
|
||||
api.use('/health', (function(req, res) {
|
||||
api.use('/health', function(req, res) {
|
||||
res.json({
|
||||
status: 'ok'
|
||||
status: 'ok',
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
api.use('/', bodyParser.urlencoded({extended: false}), new PublicAPIRouter().expressRouter());
|
||||
api.use(
|
||||
'/',
|
||||
bodyParser.urlencoded({ extended: false }),
|
||||
new PublicAPIRouter().expressRouter()
|
||||
);
|
||||
|
||||
api.use(bodyParser.json({ 'type': '*/*' , limit: maxUploadSize }));
|
||||
api.use(bodyParser.json({ type: '*/*', limit: maxUploadSize }));
|
||||
api.use(middlewares.allowCrossDomain);
|
||||
api.use(middlewares.allowMethodOverride);
|
||||
api.use(middlewares.handleParseHeaders);
|
||||
@@ -167,9 +174,12 @@ class ParseServer {
|
||||
if (!process.env.TESTING) {
|
||||
//This causes tests to spew some useless warnings, so disable in test
|
||||
/* istanbul ignore next */
|
||||
process.on('uncaughtException', (err) => {
|
||||
if (err.code === "EADDRINUSE") { // user-friendly message for this common error
|
||||
process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
|
||||
process.on('uncaughtException', err => {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
// user-friendly message for this common error
|
||||
process.stderr.write(
|
||||
`Unable to listen on port ${err.port}. The port is already in use.`
|
||||
);
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw err;
|
||||
@@ -182,12 +192,14 @@ class ParseServer {
|
||||
});
|
||||
}
|
||||
if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1') {
|
||||
Parse.CoreManager.setRESTController(ParseServerRESTController(appId, appRouter));
|
||||
Parse.CoreManager.setRESTController(
|
||||
ParseServerRESTController(appId, appRouter)
|
||||
);
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
static promiseRouter({appId}) {
|
||||
static promiseRouter({ appId }) {
|
||||
const routers = [
|
||||
new ClassesRouter(),
|
||||
new UsersRouter(),
|
||||
@@ -206,7 +218,7 @@ class ParseServer {
|
||||
new HooksRouter(),
|
||||
new CloudCodeRouter(),
|
||||
new AudiencesRouter(),
|
||||
new AggregateRouter()
|
||||
new AggregateRouter(),
|
||||
];
|
||||
|
||||
const routes = routers.reduce((memo, router) => {
|
||||
@@ -225,7 +237,7 @@ class ParseServer {
|
||||
* @param {Function} callback called when the server has started
|
||||
* @returns {ParseServer} the parse server instance
|
||||
*/
|
||||
start(options: ParseServerOptions, callback: ?()=>void) {
|
||||
start(options: ParseServerOptions, callback: ?() => void) {
|
||||
const app = express();
|
||||
if (options.middleware) {
|
||||
let middleware;
|
||||
@@ -242,7 +254,10 @@ class ParseServer {
|
||||
this.server = server;
|
||||
|
||||
if (options.startLiveQueryServer || options.liveQueryServerOptions) {
|
||||
this.liveQueryServer = ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions);
|
||||
this.liveQueryServer = ParseServer.createLiveQueryServer(
|
||||
server,
|
||||
options.liveQueryServerOptions
|
||||
);
|
||||
}
|
||||
/* istanbul ignore next */
|
||||
if (!process.env.TESTING) {
|
||||
@@ -258,7 +273,7 @@ class ParseServer {
|
||||
* @param {Function} callback called when the server has started
|
||||
* @returns {ParseServer} the parse server instance
|
||||
*/
|
||||
static start(options: ParseServerOptions, callback: ?()=>void) {
|
||||
static start(options: ParseServerOptions, callback: ?() => void) {
|
||||
const parseServer = new ParseServer(options);
|
||||
return parseServer.start(options, callback);
|
||||
}
|
||||
@@ -281,25 +296,36 @@ class ParseServer {
|
||||
|
||||
static verifyServerUrl(callback) {
|
||||
// perform a health check on the serverURL value
|
||||
if(Parse.serverURL) {
|
||||
if (Parse.serverURL) {
|
||||
const request = require('request');
|
||||
request(Parse.serverURL.replace(/\/$/, "") + "/health", function (error, response, body) {
|
||||
request(Parse.serverURL.replace(/\/$/, '') + '/health', function(
|
||||
error,
|
||||
response,
|
||||
body
|
||||
) {
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
json = null;
|
||||
}
|
||||
if (error || response.statusCode !== 200 || !json || json && json.status !== 'ok') {
|
||||
if (
|
||||
error ||
|
||||
response.statusCode !== 200 ||
|
||||
!json ||
|
||||
(json && json.status !== 'ok')
|
||||
) {
|
||||
/* eslint-disable no-console */
|
||||
console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` +
|
||||
` Cloud code and push notifications may be unavailable!\n`);
|
||||
console.warn(
|
||||
`\nWARNING, Unable to connect to '${Parse.serverURL}'.` +
|
||||
` Cloud code and push notifications may be unavailable!\n`
|
||||
);
|
||||
/* eslint-enable no-console */
|
||||
if(callback) {
|
||||
if (callback) {
|
||||
callback(false);
|
||||
}
|
||||
} else {
|
||||
if(callback) {
|
||||
if (callback) {
|
||||
callback(true);
|
||||
}
|
||||
}
|
||||
@@ -309,13 +335,13 @@ class ParseServer {
|
||||
}
|
||||
|
||||
function addParseCloud() {
|
||||
const ParseCloud = require("./cloud-code/Parse.Cloud");
|
||||
const ParseCloud = require('./cloud-code/Parse.Cloud');
|
||||
Object.assign(Parse.Cloud, ParseCloud);
|
||||
global.Parse = Parse;
|
||||
}
|
||||
|
||||
function injectDefaults(options: ParseServerOptions) {
|
||||
Object.keys(defaults).forEach((key) => {
|
||||
Object.keys(defaults).forEach(key => {
|
||||
if (!options.hasOwnProperty(key)) {
|
||||
options[key] = defaults[key];
|
||||
}
|
||||
@@ -325,15 +351,20 @@ function injectDefaults(options: ParseServerOptions) {
|
||||
options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
|
||||
}
|
||||
|
||||
options.userSensitiveFields = Array.from(new Set(options.userSensitiveFields.concat(
|
||||
defaults.userSensitiveFields,
|
||||
options.userSensitiveFields
|
||||
)));
|
||||
options.userSensitiveFields = Array.from(
|
||||
new Set(
|
||||
options.userSensitiveFields.concat(
|
||||
defaults.userSensitiveFields,
|
||||
options.userSensitiveFields
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
options.masterKeyIps = Array.from(new Set(options.masterKeyIps.concat(
|
||||
defaults.masterKeyIps,
|
||||
options.masterKeyIps
|
||||
)));
|
||||
options.masterKeyIps = Array.from(
|
||||
new Set(
|
||||
options.masterKeyIps.concat(defaults.masterKeyIps, options.masterKeyIps)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Those can't be tested as it requires a subprocess
|
||||
@@ -343,7 +374,7 @@ function configureListeners(parseServer) {
|
||||
const sockets = {};
|
||||
/* Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM if it has client connections that haven't timed out. (This is a known issue with node - https://github.com/nodejs/node/issues/2642)
|
||||
This function, along with `destroyAliveConnections()`, intend to fix this behavior such that parse server will close all open connections and initiate the shutdown process as soon as it receives a SIGINT/SIGTERM signal. */
|
||||
server.on('connection', (socket) => {
|
||||
server.on('connection', socket => {
|
||||
const socketId = socket.remoteAddress + ':' + socket.remotePort;
|
||||
sockets[socketId] = socket;
|
||||
socket.on('close', () => {
|
||||
@@ -355,9 +386,11 @@ function configureListeners(parseServer) {
|
||||
for (const socketId in sockets) {
|
||||
try {
|
||||
sockets[socketId].destroy();
|
||||
} catch (e) { /* */ }
|
||||
} catch (e) {
|
||||
/* */
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleShutdown = function() {
|
||||
process.stdout.write('Termination signal received. Shutting down.');
|
||||
|
||||
Reference in New Issue
Block a user