Skip to content

Commit e0480df

Browse files
authored
feat: Upgrade to express 5.0.1 (#9530)
BREAKING CHANGE: This upgrades the internally used Express framework from version 4 to 5, which may be a breaking change. If Parse Server is set up to be mounted on an Express application, we recommend to also use version 5 of the Express framework to avoid any compatibility issues. Note that even if there are no issues after upgrading, future releases of Parse Server may introduce issues if Parse Server internally relies on Express 5-specific features which are unsupported by the Express version on which it is mounted. See the Express [migration guide](https://expressjs.com/en/guide/migrating-5.html) and [release announcement](https://expressjs.com/2024/10/15/v5-release.html#breaking-changes) for more info.
1 parent cc8dad8 commit e0480df

26 files changed

+997
-403
lines changed

package-lock.json

Lines changed: 924 additions & 341 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@
2828
"@parse/fs-files-adapter": "3.0.0",
2929
"@parse/push-adapter": "6.10.0",
3030
"bcryptjs": "2.4.3",
31-
"body-parser": "1.20.3",
3231
"commander": "13.0.0",
3332
"cors": "2.8.5",
3433
"deepcopy": "2.1.0",
35-
"express": "4.21.2",
34+
"express": "5.0.1",
3635
"express-rate-limit": "7.5.0",
3736
"follow-redirects": "1.15.9",
3837
"graphql": "16.9.0",
@@ -58,6 +57,7 @@
5857
"punycode": "2.3.1",
5958
"rate-limit-redis": "4.2.0",
6059
"redis": "4.7.0",
60+
"router": "2.0.0",
6161
"semver": "7.7.1",
6262
"subscriptions-transport-ws": "0.11.0",
6363
"tv4": "1.3.0",

spec/HTTPRequest.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
const httpRequest = require('../lib/request'),
44
HTTPResponse = require('../lib/request').HTTPResponse,
5-
bodyParser = require('body-parser'),
65
express = require('express');
76

87
const port = 13371;
98
const httpRequestServer = `http://localhost:${port}`;
109

1110
function startServer(done) {
1211
const app = express();
13-
app.use(bodyParser.json({ type: '*/*' }));
12+
app.use(express.json({ type: '*/*' }));
1413
app.get('/hello', function (req, res) {
1514
res.json({ response: 'OK' });
1615
});

spec/ParseHooks.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const request = require('../lib/request');
44
const triggers = require('../lib/triggers');
55
const HooksController = require('../lib/Controllers/HooksController').default;
66
const express = require('express');
7-
const bodyParser = require('body-parser');
87
const auth = require('../lib/Auth');
98
const Config = require('../lib/Config');
109

@@ -17,7 +16,7 @@ describe('Hooks', () => {
1716
beforeEach(done => {
1817
if (!app) {
1918
app = express();
20-
app.use(bodyParser.json({ type: '*/*' }));
19+
app.use(express.json({ type: '*/*' }));
2120
server = app.listen(port, undefined, done);
2221
} else {
2322
done();

spec/vulnerabilities.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,10 @@ describe('Vulnerabilities', () => {
250250

251251
it_id('e8b5f1e1-8326-4c70-b5f4-1e8678dfff8d')(it)('denies creating a hook with polluted data', async () => {
252252
const express = require('express');
253-
const bodyParser = require('body-parser');
254253
const port = 34567;
255254
const hookServerURL = 'http://localhost:' + port;
256255
const app = express();
257-
app.use(bodyParser.json({ type: '*/*' }));
256+
app.use(express.json({ type: '*/*' }));
258257
const server = await new Promise(resolve => {
259258
const res = app.listen(port, undefined, () => resolve(res));
260259
});

src/Controllers/AnalyticsController.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export class AnalyticsController extends AdaptableController {
55
appOpened(req) {
66
return Promise.resolve()
77
.then(() => {
8-
return this.adapter.appOpened(req.body, req);
8+
return this.adapter.appOpened(req.body || {}, req);
99
})
1010
.then(response => {
1111
return { response: response || {} };
@@ -18,7 +18,7 @@ export class AnalyticsController extends AdaptableController {
1818
trackEvent(req) {
1919
return Promise.resolve()
2020
.then(() => {
21-
return this.adapter.trackEvent(req.params.eventName, req.body, req);
21+
return this.adapter.trackEvent(req.params.eventName, req.body || {}, req);
2222
})
2323
.then(response => {
2424
return { response: response || {} };

src/ParseServer.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// ParseServer - open-source compatible API Server for Parse apps
22

33
var batch = require('./batch'),
4-
bodyParser = require('body-parser'),
54
express = require('express'),
65
middlewares = require('./middlewares'),
76
Parse = require('parse/node').Parse,
@@ -253,6 +252,7 @@ class ParseServer {
253252
var api = express();
254253
//api.use("/apps", express.static(__dirname + "/public"));
255254
api.use(middlewares.allowCrossDomain(appId));
255+
api.use(middlewares.allowDoubleForwardSlash);
256256
// File handling needs to be before default middlewares are applied
257257
api.use(
258258
'/',
@@ -273,15 +273,16 @@ class ParseServer {
273273

274274
api.use(
275275
'/',
276-
bodyParser.urlencoded({ extended: false }),
276+
express.urlencoded({ extended: false }),
277277
pages.enableRouter
278278
? new PagesRouter(pages).expressRouter()
279279
: new PublicAPIRouter().expressRouter()
280280
);
281281

282-
api.use(bodyParser.json({ type: '*/*', limit: maxUploadSize }));
282+
api.use(express.json({ type: '*/*', limit: maxUploadSize }));
283283
api.use(middlewares.allowMethodOverride);
284284
api.use(middlewares.handleParseHeaders);
285+
api.set('query parser', 'extended');
285286
const routes = Array.isArray(rateLimit) ? rateLimit : [rateLimit];
286287
for (const route of routes) {
287288
middlewares.addRateLimit(route, options);

src/PromiseRouter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Parse from 'parse/node';
99
import express from 'express';
1010
import log from './logger';
1111
import { inspect } from 'util';
12-
const Layer = require('express/lib/router/layer');
12+
const Layer = require('router/lib/layer');
1313

1414
function validateParameter(key, value) {
1515
if (key == 'className') {

src/Routers/AggregateRouter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import UsersRouter from './UsersRouter';
66

77
export class AggregateRouter extends ClassesRouter {
88
handleFind(req) {
9-
const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
9+
const body = Object.assign(req.body || {}, ClassesRouter.JSONFromQuery(req.query));
1010
const options = {};
1111
if (body.distinct) {
1212
options.distinct = String(body.distinct);

src/Routers/AudiencesRouter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export class AudiencesRouter extends ClassesRouter {
88
}
99

1010
handleFind(req) {
11-
const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
11+
const body = Object.assign(req.body || {}, ClassesRouter.JSONFromQuery(req.query));
1212
const options = ClassesRouter.optionsFromBody(body, req.config.defaultLimit);
1313

1414
return rest

0 commit comments

Comments
 (0)