Reference
Middleware
What each middleware does, and the order they belong in.
Boot order
The sequence is load-bearing. Each step depends on the one before it.
import {
importFiles, CloudFunctionRegistry, TriggerRegistry, CronRegistry,
setupSwagger,
} from 'parse-server-kit';
// 1. Models first - @ParseClass registers the subclass as the
// decorator is evaluated, so Parse must already be global.
importFiles(join(__dirname, 'models'));
importFiles(join(__dirname, 'functions'));
// 2. Parse Server
const parseServer = ParseServer({ … });
await parseServer.start();
// 3. Middleware, in this order
app.use(removeResultMiddleware);
app.use(mountPath, validateEntityRoutes);
app.use(conditionalJsonMiddleware);
app.use(mountPath, restrictRoutes);
// 4. Mount
app.use(mountPath, parseServer.app);
// 5. Registries - AFTER the mount
CloudFunctionRegistry.initialize();
TriggerRegistry.initialize();
CronRegistry.initialize();
// 6. Docs, then 7. indexes and validators after listen()
setupSwagger(app, { title: 'My API', version: '1.0.0' });
What each one does
| Middleware | Responsibility |
|---|---|
removeResultMiddleware | Unwraps Parse's {result: …} envelope so responses look like an ordinary REST API |
validateEntityRoutes | Resolves /api/{entity}/{action} to a cloud function, enforces the declared HTTP method (405), applies the per-function rate limit, merges a GET query string into the body, and rewrites to /functions/{name} |
conditionalJsonMiddleware | JSON body parsing, skipping file upload routes |
restrictRoutes | Blocks /classes, /schemas and /batch. Applies the declared rate limit to a direct /functions/{name} call, so it cannot be skipped by going around the entity route. The declared methods are not applied there — /functions is Parse's protocol endpoint and Parse.Cloud.run always POSTs to it. Allows /health, /serverInfo, /files, registered prefixes and /functions. A master key bypasses it |
validateFunctionRoutes | Legacy /functions/* validation |
checkRateLimit(req, res, name, cfg) | In-process token bucket; answers 429 and returns false |
Security notes
- The master key is read from the
X-Parse-Master-Keyheader. The request body is still accepted for compatibility and warns once — a secret in a body ends up in every log that records bodies. - Rate limiting is per process. Nothing is shared between instances, and a restart clears it.
/filesis allowed through without authentication. parse-server 9.8+ offersfileDownloadto restrict it.
Why /classes is blocked
Parse exposes generic CRUD over every class. Blocking it means clients can only reach
the endpoints you declared, so class-level permissions are a second line of defence
rather than the only one.