Skip to content

Conversation

@J1vvoo
Copy link

@J1vvoo J1vvoo commented Dec 2, 2025

Pull Request

Issue

Closes: #9951

Approach

Implemented global and per-route security header support in PagesRouter.

  • Added pages.headers for global HTML-page headers
  • Added headers option for each custom route
  • Updated pageResponse, fileResponse, redirectResponse to merge headers properly
  • Ensures backward compatibility and applies headers only to HTML page responses

Tasks

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)

Summary by CodeRabbit

  • New Features
    • Added configurable global headers to apply default headers across all page responses.
    • Added per-route headers to apply custom headers for specific page routes.
    • Improved header handling so global and route-specific headers are merged and consistently propagated through all response paths.

✏️ Tip: You can customize this high-level summary in your review settings.

@parse-github-assistant
Copy link

🚀 Thanks for opening this pull request!

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Dec 2, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

📝 Walkthrough

Walkthrough

Adds a new headers option to PagesOptions and PagesRoute, and updates PagesRouter to accept, propagate, and merge per-route headers with global and per-call headers; expressRouter now applies configured security and custom headers before delegating to downstream handlers.

Changes

Cohort / File(s) Summary
Configuration Definitions
src/Options/Definitions.js
Added headers property to PagesOptions (global, env: PARSE_SERVER_PAGES_HEADERS) and to PagesRoute (per-route, env: PARSE_SERVER_PAGES_ROUTE_HEADERS), both using objectParser with default {} and exposed in public declarations.
Pages router & response plumbing
src/Routers/PagesRouter.js
Extended method signatures: goToPage(req, page, params = {}, responseType, routeHeaders = {}), pageResponse(path, params = {}, placeholders = {}, routeHeaders = {}), fileResponse(path, routeHeaders = {}), redirectResponse(url, params, routeHeaders = {}). Threaded routeHeaders through mountCustomRoutes, redirect/page/file responses, and unified header merging (global → route → per-call). expressRouter() applies security and custom headers from _pagesOptions before delegating; custom route handlers forward routeHeaders into goToPage calls.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client
participant ExpressMiddleware as Express (PagesRouter.expressRouter)
participant CustomRouteHandler as Route Handler
participant PagesRouter as PagesRouter.goToPage
participant ResponseBuilder as pageResponse/fileResponse/redirectResponse
Client->>ExpressMiddleware: HTTP request
ExpressMiddleware->>ExpressMiddleware: apply global security & custom headers
ExpressMiddleware->>CustomRouteHandler: dispatch to mounted route
CustomRouteHandler->>PagesRouter: call goToPage(..., routeHeaders)
PagesRouter->>ResponseBuilder: build response with global + route + per-call headers
ResponseBuilder-->>Client: HTTP response (merged headers)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify header precedence and merging in pageResponse(), fileResponse(), and redirectResponse() (global → route → per-call).
  • Confirm expressRouter() applies security headers correctly and allows overrides from custom headers or per-route headers.
  • Ensure mountCustomRoutes() and custom route handlers consistently pass routeHeaders to goToPage().
  • Check backward compatibility for callers of modified methods and that default {} prevents breaking behavior.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides good approach details but fails to address critical implementation gaps noted by reviewers: headers properties are missing from src/Options/index.js and npm run definitions was not executed. Add headers properties to PagesOptions and PagesRoute in src/Options/index.js, then run npm run definitions to properly generate Definitions.js and docs.js changes.
Out of Scope Changes check ⚠️ Warning Changes were added directly to src/Options/Definitions.js without following the required workflow (modifying src/Options/index.js first and running npm run definitions), which is outside the proper development process for Parse Server options. Revert manual Definitions.js changes and instead add properties to src/Options/index.js, then execute npm run definitions to auto-generate all required file updates.
Linked Issues check ❓ Inconclusive PR addresses #9951 partially by implementing headers for PagesRouter only, but scope appears narrower than the linked issue's requirement for global application across entire ParseServer.app request pipeline. Clarify whether the PR is a partial implementation (PagesRouter-only) of #9951 or if scope differs; ensure full pipeline coverage as requested in the issue.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding support for global and per-route security headers in PagesRouter.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6001107 and 81614be.

📒 Files selected for processing (1)
  • src/Options/Definitions.js (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-12-02T06:55:53.788Z
Learning: When reviewing Parse Server PRs that add or modify Parse Server options, always verify that changes are properly reflected in three files: src/Options/index.js (where changes originate), src/Options/Definitions.js, and src/Options/docs.js. The correct workflow is: make changes in index.js first, then run `npm run definitions` to automatically replicate the changes to Definitions.js and docs.js.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: For new Parse Server options, verify that the option is documented in src/Options/index.js and that npm run definitions has been executed to reflect changes in src/Options/docs.js and src/Options/Definitions.js. README.md documentation is a bonus but not required for new options.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.
📚 Learning: 2025-11-08T13:46:04.940Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: For new Parse Server options, verify that the option is documented in src/Options/index.js and that npm run definitions has been executed to reflect changes in src/Options/docs.js and src/Options/Definitions.js. README.md documentation is a bonus but not required for new options.

Applied to files:

  • src/Options/Definitions.js
📚 Learning: 2025-12-02T06:55:53.788Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-12-02T06:55:53.788Z
Learning: When reviewing Parse Server PRs that add or modify Parse Server options, always verify that changes are properly reflected in three files: src/Options/index.js (where changes originate), src/Options/Definitions.js, and src/Options/docs.js. The correct workflow is: make changes in index.js first, then run `npm run definitions` to automatically replicate the changes to Definitions.js and docs.js.

Applied to files:

  • src/Options/Definitions.js
🧬 Code graph analysis (1)
src/Options/Definitions.js (1)
resources/buildConfigDefinitions.js (1)
  • parsers (12-12)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Benchmarks
🔇 Additional comments (1)
src/Options/Definitions.js (1)

812-817: PagesRoute.headers shape is consistent and aligns with PagesOptions.headers.

Per‑route headers are defined analogously to the global option:

  • pages‑route‑scoped env name PARSE_SERVER_PAGES_ROUTE_HEADERS.
  • parsers.objectParser with default: {}.
  • Help text clearly indicates route‑specific application.

This is a good, minimal public surface for route‑level customization and matches the global headers option semantics.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@J1vvoo J1vvoo force-pushed the test/pagesrouter-secure-headers branch from 15828af to f872368 Compare December 2, 2025 06:21
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Routers/PagesRouter.js (1)

260-314: Route-level headers are dropped for localized/custom-URL pages

goToPage accepts routeHeaders and passes them to redirectResponse / pageResponse only in the non-localized, non-custom-URL branch. That means:

  • When pages.enableLocalization is true and a locale is present, the localized branch never forwards routeHeaders.
  • When a customUrl is configured for a page, redirectResponse is called without routeHeaders.
  • mountCustomRoutes correctly extracts headers: routeHeaders from the handler and passes them into goToPage, but those headers are silently ignored in the above scenarios.

As a result, per-route headers won’t be applied for localized pages or custom URLs, which is particularly problematic for security-related headers.

Consider updating goToPage to always propagate routeHeaders:

   const customUrl = config.pages.customUrls[page.id];
   if (customUrl && !Utils.isPath(customUrl)) {
-      return this.redirectResponse(customUrl, params);
+      return this.redirectResponse(customUrl, params, routeHeaders);
   }

   // ...

   if (config.pages.enableLocalization && locale) {
     return Utils.getLocalizedPath(defaultPath, locale).then(({ path, subdir }) =>
       redirect
-        ? this.redirectResponse(
-            this.composePageUrl(defaultFile, config.publicServerURL, subdir),
-            params
-          )
-        : this.pageResponse(path, params, placeholders)
+        ? this.redirectResponse(
+            this.composePageUrl(defaultFile, config.publicServerURL, subdir),
+            params,
+            routeHeaders
+          )
+        : this.pageResponse(path, params, placeholders, routeHeaders)
     );
   } else {
     return redirect
       ? this.redirectResponse(defaultUrl, params, routeHeaders)
       : this.pageResponse(defaultPath, params, placeholders, routeHeaders);
   }

With this change, the existing calls from mountCustomRoutes (goToPage(req, page, query, false, routeHeaders)) will behave consistently regardless of localization or custom URLs.

Also applies to: 576-609, 711-732

🧹 Nitpick comments (4)
src/Options/Definitions.js (1)

782-787: Ensure new pages.headers / route headers are backed by Options/index.js and docs

The new PagesOptions.headers and PagesRoute.headers entries look structurally fine, but since this file is generated, please confirm:

  • The headers fields are defined in src/Options/index.js and this file was produced via npm run definitions, not edited directly.
  • The corresponding docs (in src/Options/docs.js and any user-facing configuration docs) mention pages.headers and route-level headers so users can actually discover and configure them (including via PARSE_SERVER_PAGES_HEADERS).

You may also want to tighten the help text to clarify that these headers are applied to HTML page/redirect responses produced by PagesRouter rather than literally all possible responses (e.g. JSON XHR responses from the same router).

Based on learnings, this keeps generator source and docs aligned.

Also applies to: 805-810

src/Routers/PagesRouter.js (3)

69-76: Avoid duplicating pages config state (_pagesOptions vs pagesConfig)

this._pagesOptions and this.pagesConfig are both set to the same pages object and then used in different parts of the class. This works, but it introduces two sources of truth for the same config. Consider standardizing on one property (e.g. this.pagesConfig) and deriving globalHeaders from it to reduce the chance of future divergence.


432-495: Global pages.headers are now applied to non-HTML static assets as well

pageResponse and fileResponse both merge this.globalHeaders into the returned headers. Because staticRoute uses fileResponse for non-HTML resources (e.g. images, CSS, JS), global headers from pages.headers will now also be attached to those static assets, not just HTML pages.

That may be fine (and often desirable) for security headers, but it slightly diverges from the “global HTML-page headers” wording in the option help text. If you intend headers strictly for HTML/redirect responses, you may want to:

  • Either gate globalHeaders in fileResponse based on path.endsWith('.html'), or
  • Relax the option help text to describe that headers apply to all responses produced via PagesRouter’s helpers (including static assets).

The current merge order { ...this.globalHeaders, ...routeHeaders, ...paramHeaders } looks good: route- and param-derived headers override global ones as expected.


748-775: Clarify and surface pages.secureHeaders / pages.customHeaders as first-class options

The new expressRouter() middleware:

  • Enables clickjacking protection headers by default unless pages.secureHeaders === false.
  • Applies any pages.customHeaders on every request handled by this router.

This is a solid pattern, but a couple of points are worth tightening up:

  1. Config surface alignment
    options.secureHeaders and options.customHeaders are read from this._pagesOptions, but there are no corresponding entries for these fields in PagesOptions within Options/Definitions.js. If these are meant to be supported configuration options (especially via environment variables), they should be added to PagesOptions in src/Options/index.js and the definitions/docs regenerated so users can discover and set them consistently.

  2. Default behavior vs backward compatibility
    Because enableSecureHeaders defaults to true, existing deployments will suddenly get X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none' on all pages served by PagesRouter. That’s usually a good security default, but it may be a breaking change for apps that intentionally embed these pages in iframes. Please double-check with maintainers whether this should be opt-in (secureHeaders: true) or opt-out as coded here.

If you keep the current default, it would be helpful to document pages.secureHeaders / pages.customHeaders prominently so operators know how to override or disable these headers when needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b479102 and 15828af.

📒 Files selected for processing (2)
  • src/Options/Definitions.js (2 hunks)
  • src/Routers/PagesRouter.js (11 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-08T13:46:04.940Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: For new Parse Server options, verify that the option is documented in src/Options/index.js and that npm run definitions has been executed to reflect changes in src/Options/docs.js and src/Options/Definitions.js. README.md documentation is a bonus but not required for new options.

Applied to files:

  • src/Options/Definitions.js
🧬 Code graph analysis (1)
src/Routers/PagesRouter.js (2)
src/GraphQL/loaders/filesMutations.js (1)
  • headers (12-12)
src/PromiseRouter.js (2)
  • headers (143-143)
  • url (140-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Benchmarks

@J1vvoo J1vvoo force-pushed the test/pagesrouter-secure-headers branch from f872368 to 6001107 Compare December 2, 2025 06:24
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Routers/PagesRouter.js (1)

260-314: Inconsistent header propagation in early return paths.

The routeHeaders parameter is only passed to redirectResponse and pageResponse in the final return statements (lines 312-313), but not in earlier return paths:

  • Line 291: Custom URL redirect doesn't pass routeHeaders
  • Lines 304-308: Localized page responses don't pass routeHeaders

This means route-specific headers (including security headers from custom routes) won't be applied when custom URLs are configured or localization is enabled, creating inconsistent security behavior.

Apply this diff to ensure consistent header propagation:

     // If custom URL is set redirect to it without localization
     const customUrl = config.pages.customUrls[page.id];
     if (customUrl && !Utils.isPath(customUrl)) {
-      return this.redirectResponse(customUrl, params);
+      return this.redirectResponse(customUrl, params, routeHeaders);
     }
 
     // Get JSON placeholders
     let placeholders = {};
     if (config.pages.enableLocalization && config.pages.localizationJsonPath) {
       placeholders = this.getJsonPlaceholders(locale, params);
     }
 
     // Send response
     if (config.pages.enableLocalization && locale) {
       return Utils.getLocalizedPath(defaultPath, locale).then(({ path, subdir }) =>
         redirect
           ? this.redirectResponse(
             this.composePageUrl(defaultFile, config.publicServerURL, subdir),
-            params
+            params,
+            routeHeaders
           )
-          : this.pageResponse(path, params, placeholders)
+          : this.pageResponse(path, params, placeholders, routeHeaders)
       );
     } else {
🧹 Nitpick comments (1)
src/Routers/PagesRouter.js (1)

764-768: Consider checking existing headers before applying customHeaders.

The customHeaders are applied unconditionally, which means they will override any headers set by external middleware. While this might be intentional to ensure configured headers always apply, it could be surprising behavior.

Consider whether customHeaders should:

  1. Always override (current behavior) - ensures configured headers are enforced
  2. Only apply if not already set (like security headers) - allows more flexibility

If you want to allow external middleware to take precedence, apply this diff:

     if (options.customHeaders) {
       Object.entries(options.customHeaders).forEach(([key, value]) => {
-        res.set(key, value);
+        if (!res.get(key)) {
+          res.set(key, value);
+        }
       });
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15828af and 6001107.

📒 Files selected for processing (2)
  • src/Options/Definitions.js (2 hunks)
  • src/Routers/PagesRouter.js (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Options/Definitions.js
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Benchmarks
🔇 Additional comments (7)
src/Routers/PagesRouter.js (7)

71-72: LGTM!

The constructor properly stores the pages options and initializes global headers with a safe fallback to an empty object.


432-473: LGTM!

The header merging logic correctly prioritizes headers from most specific to least specific: parameter headers override route headers, which override global headers. The implementation properly uses the spread operator to achieve this precedence.


576-610: LGTM!

The header merging logic is consistent with pageResponse, correctly prioritizing parameter headers over route headers over global headers.


720-730: LGTM!

The custom route handler correctly extracts headers from the route response and propagates them through goToPage, enabling per-route header customization as intended.


748-775: Verify scope against PR objectives for issue #9951.

The implementation correctly wraps the parent router with middleware to apply security headers (X-Frame-Options and Content-Security-Policy) before route handling. However, confirm whether this PagesRouter-specific approach aligns with the issue requirements—if the goal is ParseServer-wide header coverage, verify that security headers are also implemented at the application level, not solely in PagesRouter routes.


480-495: Verify header handling in staticRoute context.

The code correctly merges globalHeaders and routeHeaders in fileResponse. However, without confirming the actual usage patterns of staticRoute and whether it intentionally omits routeHeaders, the security and design implications cannot be assessed. Verify that static route behavior aligns with security requirements and design intent.


753-762: Verify the security headers default behavior and header precedence logic.

The middleware sets security headers (X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none') only if they aren't already present. Since this middleware runs before route handlers, the res.get() checks only detect headers set by external middleware that runs earlier.

Clarify the intended behavior:

  1. Should route-specific headers (from pageResponse/redirectResponse) be able to override these security defaults?
  2. How does PromiseRouter merge headers set via res.set() in middleware with headers returned in the response object?

If route handlers should be able to override security headers, consider applying these defaults at a later stage or checking both res headers and response object headers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the contribution guide for how to add a new option.

@mtrezza
Copy link
Member

mtrezza commented Dec 2, 2025

@coderabbitai When reviewing a PR that contains changes to the Parse Server options, always make sure the changes are reflected in src/Options/Definitions.js, src/Options/docs.js and src/Options/index.js. The changes are made originally in index.js and then via npm run definitions replicated in the other 2 files.

@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the new headers options are present in all three options files

echo "=== Checking src/Options/index.js ==="
rg -n -A5 -B2 'headers.*:.*{' src/Options/index.js | head -50

echo -e "\n=== Checking src/Options/Definitions.js ==="
rg -n -A5 -B2 'headers.*:.*{' src/Options/Definitions.js | head -50

echo -e "\n=== Checking src/Options/docs.js ==="
rg -n -A5 -B2 'headers.*:.*{' src/Options/docs.js | head -50

echo -e "\n=== Checking if PagesOptions headers is defined in index.js ==="
rg -n -C10 'PagesOptions' src/Options/index.js | rg -C5 'headers'

echo -e "\n=== Checking if PagesRoute headers is defined in index.js ==="
rg -n -C10 'PagesRoute.*{' src/Options/index.js | rg -C5 'headers'

Length of output: 608


🏁 Script executed:

#!/bin/bash
# Check if the new headers options are present in all three options files

echo "=== Checking src/Options/index.js ==="
rg -n 'headers' src/Options/index.js

echo -e "\n=== Checking src/Options/Definitions.js ==="
rg -n 'headers' src/Options/Definitions.js

echo -e "\n=== Checking src/Options/docs.js ==="
rg -n 'headers' src/Options/docs.js

echo -e "\n=== Detailed look at PagesOptions in index.js ==="
ast-grep --pattern 'PagesOptions = {
  $$$
}'

echo -e "\n=== Detailed look at PagesRoute in index.js ==="
ast-grep --pattern 'PagesRoute = {
  $$$
}'

Length of output: 521


🏁 Script executed:

#!/bin/bash
# Get detailed sections from all three files

echo "=== PagesOptions section in src/Options/index.js ==="
rg -n -A50 'export class PagesOptions' src/Options/index.js

echo -e "\n=== PagesRoute section in src/Options/index.js ==="
rg -n -A30 'export class PagesRoute' src/Options/index.js

echo -e "\n=== Lines around headers in Definitions.js ==="
rg -n -B10 -A10 'headers.*{' src/Options/Definitions.js | head -60

echo -e "\n=== Check docs.js for PagesOptions ==="
rg -n -A50 '@property.*pages' src/Options/docs.js | head -80

Length of output: 19811


🏁 Script executed:

#!/bin/bash
# Get detailed view of how options are structured in these files

echo "=== Full structure of PagesOptions in index.js ==="
rg -n -A100 'PagesOptions' src/Options/index.js | head -150

echo -e "\n=== Full structure of PagesOptions in Definitions.js ==="
rg -n -B5 -A20 'PagesOptions' src/Options/Definitions.js | head -100

echo -e "\n=== Check around line 782 in Definitions.js (where headers appears) ==="
sed -n '770,800p' src/Options/Definitions.js

echo -e "\n=== Full structure check in docs.js for PagesOptions details ==="
rg -n -A100 'PagesOptions.*=|class PagesOptions' src/Options/docs.js | head -150

Length of output: 12941


🏁 Script executed:

#!/bin/bash
# Verify PagesRoute headers and check docs.js

echo "=== PagesRoute section in Definitions.js around line 805 ==="
sed -n '795,820p' src/Options/Definitions.js

echo -e "\n=== Check if docs.js has PagesOptions type definition ==="
rg -n -A50 '@typedef.*PagesOptions' src/Options/docs.js

echo -e "\n=== Check if docs.js has PagesRoute type definition ==="
rg -n -A50 '@typedef.*PagesRoute' src/Options/docs.js

Length of output: 1014


@mtrezza, I've verified the Parse Server options files and found an issue with the workflow in this PR:

Current state:

  • src/Options/Definitions.js - Contains the new headers properties for both PagesOptions (line 782) and PagesRoute (line 805)
  • src/Options/index.js - Missing the headers properties in both PagesOptions interface (lines 396-426) and PagesRoute interface (lines 428-435)
  • src/Options/docs.js - No typedef documentation for these properties

The issue:
The changes were added directly to Definitions.js instead of following the correct workflow. According to your guidance, changes should originate in index.js and then be replicated to the other files via npm run definitions.

Required fix:
The PR author (@J1vvoo) needs to:

  1. Add the headers property to the PagesOptions interface in src/Options/index.js:
export interface PagesOptions {
  // ... existing properties ...
  /* Global headers applied to all PagesRouter responses.
  :DEFAULT: {} */
  headers: ?Object;
}
  1. Add the headers property to the PagesRoute interface in src/Options/index.js:
export interface PagesRoute {
  // ... existing properties ...
  /* Headers applied only to this specific page route.
  :DEFAULT: {} */
  headers: ?Object;
}
  1. Run npm run definitions to replicate changes to Definitions.js and docs.js

I'll remember this verification requirement for future Parse Server PRs. Thank you for the guidance!


✏️ Learnings added
Learnt from: mtrezza
URL: https://github.com/parse-community/parse-server/pull/9958

Timestamp: 2025-12-02T06:55:53.788Z
Learning: When reviewing Parse Server PRs that add or modify Parse Server options, always verify that changes are properly reflected in three files: src/Options/index.js (where changes originate), src/Options/Definitions.js, and src/Options/docs.js. The correct workflow is: make changes in index.js first, then run `npm run definitions` to automatically replicate the changes to Definitions.js and docs.js.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: For new Parse Server options, verify that the option is documented in src/Options/index.js and that npm run definitions has been executed to reflect changes in src/Options/docs.js and src/Options/Definitions.js. README.md documentation is a bonus but not required for new options.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:24.824Z
Learning: For Parse Server PRs, always suggest an Angular-style PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion with every new commit to the PR.

Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:446-454
Timestamp: 2025-08-27T09:08:34.252Z
Learning: When analyzing function signature changes in Parse Server codebase, verify that call sites are actually incorrect before flagging them. Passing tests are a strong indicator that function calls are already properly aligned with new signatures.

Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: spec/CloudCode.spec.js:446-469
Timestamp: 2025-08-26T14:06:31.853Z
Learning: In the Parse Server codebase, when handling query objects in maybeRunAfterFindTrigger, objects without a where property that contain options like limit/skip should be treated as query JSON with an empty where clause using the spread pattern { where: {}, ...query }, not nested as { where: query }.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Learnt from: RahulLanjewar93
Repo: parse-community/parse-server PR: 9744
File: spec/ParseLiveQuery.spec.js:0-0
Timestamp: 2025-04-30T19:31:35.344Z
Learning: In the Parse Server codebase, the functions in QueryTools.js are typically tested through end-to-end behavior tests rather than direct unit tests, even though the functions are exported from the module.

@codecov
Copy link

codecov bot commented Dec 2, 2025

Codecov Report

❌ Patch coverage is 84.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.71%. Comparing base (d4c6de0) to head (6001107).
⚠️ Report is 11 commits behind head on alpha.

Files with missing lines Patch % Lines
src/Routers/PagesRouter.js 84.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #9958      +/-   ##
==========================================
+ Coverage   93.08%   93.71%   +0.63%     
==========================================
  Files         188      188              
  Lines       15298    15314      +16     
  Branches      177      177              
==========================================
+ Hits        14240    14352     +112     
+ Misses       1046      950      -96     
  Partials       12       12              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Global Clickjacking Protection Headers to ParseServer.app

3 participants