Skip to content

Conversation

@d-gubert
Copy link
Member

@d-gubert d-gubert commented Jan 17, 2026

Proposed changes (including videos or screenshots)

  • Remove duplicated calls to parseBodyParams and parseQueryParams in RocketChatAPIRouter
  • Prevent logger middleware from consuming the request body and trying to parse it to JSON when the env var is not set
  • Redact the password field when logging requests
  • Fix schema definition for Livechat custom fields save request

Issue(s)

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • Security & Privacy

    • Passwords are now redacted from logged request payloads and logging is streamlined.
  • Bug Fixes & Improvements

    • Request body and query parameters are consistently populated for handlers; API action context now exposes route and incoming request info.
    • Form-urlencoded automatic payload override removed; payload parsing handles JSON and form data more robustly.
    • Livechat custom fields accept nullable IDs and enforce identifier patterns for consistency.

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

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 17, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is targeting the wrong base branch. It should target 8.2.0, but it targets 8.1.0

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Jan 17, 2026

⚠️ No Changeset found

Latest commit: 5ffad11

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

Caution

Review failed

The head commit changed during the review from 3ad9b41 to 5ffad11.

Walkthrough

Centralizes request parsing into Router, makes payload extraction asynchronous and request-centric, integrates password redaction in logging, removes runtime bodyParams-override population, and relaxes/aligns customFieldId handling across schema, types, and model to allow null and enforce pattern via types.

Changes

Cohort / File(s) Summary
Router & Request Context
packages/http-router/src/Router.ts, apps/meteor/app/api/server/router.ts
Introduced InnerRouter type and initialize innerRouter = new Hono(); parseBodyParams is now async and returns parsed body (JSON/form), Router stores bodyParams/queryParams on Hono context; APIActionContext types expanded to include route and incoming, and param types changed to Record<string, unknown>.
Logging / Payload Extraction
apps/meteor/app/api/server/middlewares/logger.ts, apps/meteor/server/lib/logger/logPayloads.ts
Replaced synchronous payload extraction with async getRestPayload(request) (handles multipart/form-data by returning a placeholder); logger now awaits payload inline and uses redact to hide passwords when building child logger.
Integrations & Middleware
apps/meteor/app/integrations/server/api/api.ts
Removed runtime population of bodyParams-override for form-urlencoded payloads; no override c.set calls remain.
Livechat Custom Fields (API, Types, Model)
apps/meteor/app/livechat/server/api/v1/customField.ts, packages/rest-typings/src/v1/omnichannel.ts, packages/model-typings/src/models/ILivechatCustomFieldModel.ts, packages/models/src/models/LivechatCustomField.ts
Removed endpoint-level regex precheck for customFieldId; schema allows `customFieldId: string

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Router
  participant LoggerMiddleware as Logger
  participant PayloadSvc as getRestPayload
  participant Handler

  Client->>Router: HTTP request
  Router->>Router: async parse query + body → c.set('queryParams','bodyParams')
  Router->>Logger: invoke logger middleware
  Logger->>PayloadSvc: await getRestPayload(request)
  PayloadSvc-->>Logger: payload | "{ payload: '[multipart/form-data]' }" | null
  Logger->>Handler: call handler (context includes body/query and logs with redacted payload)
  Handler-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • sampaiodiego
  • tassoevan

Poem

🐇
I hopped through routes and parsed the stream,
I nudged the logger to hide the cream,
Async payloads now rest in place,
Fields aligned and patterns trace,
A little rabbit twitches, pleased—hop, scheme! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'chore: api http router improvements' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes in the changeset. Consider a more descriptive title that captures the main change, such as 'refactor: consolidate payload parsing and add password redaction in API router' or 'refactor: dedup body/query parsing and redact logs in HTTP router'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/router-improvements

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.

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 12a4f8f to b1b33d3 Compare January 17, 2026 00:19
@codecov
Copy link

codecov bot commented Jan 17, 2026

Codecov Report

❌ Patch coverage is 78.94737% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.84%. Comparing base (c107092) to head (5ffad11).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38227      +/-   ##
===========================================
+ Coverage    70.73%   70.84%   +0.10%     
===========================================
  Files         3158     3159       +1     
  Lines       109359   109383      +24     
  Branches     19695    19703       +8     
===========================================
+ Hits         77358    77489     +131     
+ Misses       29966    29869      -97     
+ Partials      2035     2025      -10     
Flag Coverage Δ
e2e 60.39% <ø> (+0.10%) ⬆️
e2e-api 49.15% <20.00%> (+1.09%) ⬆️
unit 71.96% <100.00%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 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.

@d-gubert d-gubert added this to the 8.1.0 milestone Jan 17, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 17, 2026

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/23 21:51 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-38227
  • Baseline: develop
  • Timestamp: 2026-01-23 21:51:48 UTC
  • Historical data points: 30

Updated: Fri, 23 Jan 2026 21:51:49 GMT

if (options.query) {
const validatorFn = options.query;
if (typeof options.query === 'function' && !validatorFn(queryParams)) {
if (typeof options.query === 'function' && !validatorFn(structuredClone(queryParams))) {
Copy link
Member Author

Choose a reason for hiding this comment

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

validatorFn mutates its input, which causes some weird behaviors that break tests. Cloning the input "solves" the issues, but defeats the purpose of removing the second calls to parseBodyParams and parseQueryParams.

I think it is valuable to actually take a look at the breaking tests and make the system adapt to the mutatons that happen in those validatorFn calls

@d-gubert d-gubert force-pushed the chore/router-improvements branch from dd78dad to 536fd45 Compare January 20, 2026 23:28
@d-gubert
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/rest-typings/src/v1/omnichannel.ts (1)

4502-4505: Type guard does not match schema nullability for customFieldId.

The schema defines customFieldId with nullable: true and no required array (making it optional), but the type guard narrows to customFieldId: string. After validation, customFieldId could be null or omitted (undefined), violating the type guard. Align the generic type to customFieldId?: string | null to match the schema.

Suggested fix
 export const isPOSTLivechatSaveCustomFieldsParams = ajv.compile<{
-	customFieldId: string;
+	customFieldId?: string | null;
 	customFieldData: Omit<ILivechatCustomField, '_id' | '_updatedAt'> & { field: string };
 }>(POSTLivechatSaveCustomFieldsSchema);
🤖 Fix all issues with AI agents
In `@packages/rest-typings/src/v1/omnichannel.ts`:
- Around line 4446-4457: Update the regex character classes to move the hyphen
to the end so they read `[0-9a-zA-Z_-]` for both customFieldId and
customFieldData.field to avoid creating an unintended range; also reconcile the
nullable mismatch by either removing `nullable: true` from the `customFieldId`
schema or updating the type guard that references `customFieldId` (the check
near the type guard around line ~4502) to accept `string | null` so schema and
runtime types match.
🧹 Nitpick comments (1)
packages/http-router/src/Router.ts (1)

157-175: Align bodyParams typing with possible JSON shapes.
request.raw.clone().json() can return arrays or primitives, but the context types are Record<string, unknown>. Consider normalizing non‑object bodies to {} or widening the type so downstream code doesn’t rely on an incorrect shape.

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 536fd45 to 2186968 Compare January 21, 2026 00:39
@d-gubert d-gubert marked this pull request as ready for review January 21, 2026 11:59
@d-gubert d-gubert requested review from a team as code owners January 21, 2026 11:59
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 9 files

@ggazzo ggazzo modified the milestones: 8.1.0, 8.2.0 Jan 21, 2026
@ricardogarim
Copy link
Contributor

ricardogarim commented Jan 21, 2026

While reviewing the bodyParams-override removal, which looks correct since parseBodyParams never used the extra parameter, I noticed that incoming webhooks receiving application/x-www-form-urlencoded with payload={...json...} (Slack/GitHub format) have been broken for a while. The JSON is never unwrapped from the payload field.

Created CORE-1741 to track this separately.

@sampaiodiego
Copy link
Member

@ricardogarim are they really broken? I've found this test to validate it (should) be working:

it('should send a message if the payload is a application/x-www-form-urlencoded JSON', async () => {
const payload = { msg: `Message as x-www-form-urlencoded JSON sent successfully at #${Date.now()}` };
await request
.post(`/hooks/${integration._id}/${integration.token}`)
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(`payload=${JSON.stringify(payload)}`)
.expect(200)
.expect(async () => {
return request
.get(api('channels.messages'))
.set(credentials)
.query({
roomId: 'GENERAL',
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('messages').and.to.be.an('array');
expect(!!(res.body.messages as IMessage[]).find((m) => m.msg === payload.msg)).to.be.true;
});
});
});

@sampaiodiego
Copy link
Member

@d-gubert maybe the Livechat changes could be in another PR? they look like regular changes not necessarily related to "api http router improments"

@d-gubert
Copy link
Member Author

d-gubert commented Jan 21, 2026

@d-gubert maybe the Livechat changes could be in another PR? they look like regular changes not necessarily related to "api http router improments"

We need to modify that endpoint, otherwise tests fail because of this #38227 (comment) (there was an example of CI run with the tests failing, but I rebased... 😬 ) (actually, found the run https://github.com/RocketChat/Rocket.Chat/actions/runs/21084954407/job/60650568531?pr=38227)

I can make a much more contrived change just to make sure the tests are passing, then open a new PR with the appropriate changes to schemas and all. But the endpoint can't go unscathed 😛

@d-gubert
Copy link
Member Author

Forgot to mention @sampaiodiego #38227 (comment) 😬

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 2186968 to 5ffad11 Compare January 23, 2026 15:55
Copy link
Contributor

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/models/src/models/LivechatCustomField.ts (1)

52-75: Return value missing _id in update path.

When updating an existing record (_id is truthy), the returned record object lacks the _id property, which violates the ILivechatCustomField return type. The insert path correctly assigns record._id = field, but the update path does not preserve the ID on the returned object.

🐛 Proposed fix
 	async createOrUpdateCustomField(
 		_id: string | null,
 		field: string,
 		label: ILivechatCustomField['label'],
 		scope: ILivechatCustomField['scope'],
 		visibility: ILivechatCustomField['visibility'],
 		extraData: any,
 	) {
 		const record = {
 			label,
 			scope,
 			visibility,
 			...extraData,
 		};

 		if (_id) {
 			await this.updateOne({ _id }, { $set: record });
+			record._id = _id;
 		} else {
 			record._id = field;
 			await this.insertOne(record);
 		}

 		return record;
 	}
🤖 Fix all issues with AI agents
In `@apps/meteor/app/api/server/router.ts`:
- Around line 44-49: The APIActionContext construction should defensively
default potentially-undefined context entries; update the code that builds
APIActionContext (the object with requestIp, urlParams, queryParams, bodyParams,
request) to use c.get('bodyParams') ?? {} and c.get('queryParams') ?? {} so
bodyParams and queryParams are always objects even if c.get(...) returns
undefined, keeping the existing fields (e.g., requestIp: c.get('remoteAddress')
and urlParams: req.param()) unchanged.

Comment on lines 44 to 49
const context: APIActionContext = {
requestIp: c.get('remoteAddress'),
urlParams: req.param(),
queryParams,
bodyParams,
queryParams: c.get('queryParams'),
bodyParams: c.get('bodyParams'),
request,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's look at the router.ts file around lines 44-49
cat -n apps/meteor/app/api/server/router.ts | sed -n '35,60p'

Repository: RocketChat/Rocket.Chat

Length of output: 982


🏁 Script executed:

#!/bin/bash
# Search for middleware/handlers that set bodyParams and queryParams
rg -n 'bodyParams|queryParams' apps/meteor/app/api/server/ -B2 -A2 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 50379


🏁 Script executed:

#!/bin/bash
# Search for middleware or handlers related to parameter parsing
rg -n 'application/x-www-form-urlencoded|payload' apps/meteor/app/api/server/ -B3 -A3 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 1039


🏁 Script executed:

#!/bin/bash
# Search for where middleware sets bodyParams and queryParams
rg -n 'c\.set.*bodyParams|c\.set.*queryParams|set\(.*bodyParams|set\(.*queryParams' apps/meteor/app/api/server/ -B3 -A3 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Look for middleware setup in router or main API files
rg -n 'middleware|use\(|hook|Hono' apps/meteor/app/api/server/router.ts -B2 -A5 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 754


🏁 Script executed:

#!/bin/bash
# Search for where request bodies are parsed or params are extracted
rg -n 'parseBody|parseForm|urlencoded|form-data|bodyParser|parseRequest' apps/meteor/app/api/server/ -B2 -A3 -t ts | head -100

Repository: RocketChat/Rocket.Chat

Length of output: 2725


🏁 Script executed:

#!/bin/bash
# Find Router class import and definition
rg -n 'class Router|import.*Router' apps/meteor/app/api/server/router.ts -B1 -A1 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 223


🏁 Script executed:

#!/bin/bash
# Look for the definition.ts file and Router class
find apps/meteor/app/api/server -name "*.ts" -type f | xargs rg -l 'class Router|interface APIActionContext' | head -5

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Search for where bodyParams is populated - likely in middleware or parent setup
rg -n 'bodyParams.*=|queryParams.*=' apps/meteor/app/api/server -t ts --max-count=20

Repository: RocketChat/Rocket.Chat

Length of output: 4158


🏁 Script executed:

#!/bin/bash
# Search for middleware, hooks, or setup files in api/server
fd -a '\.ts$' apps/meteor/app/api/server | grep -E '(middleware|setup|init|hook)' | head -20

Repository: RocketChat/Rocket.Chat

Length of output: 792


🏁 Script executed:

#!/bin/bash
# Check definition.ts for Router setup
cat -n apps/meteor/app/api/server/definition.ts | head -100

Repository: RocketChat/Rocket.Chat

Length of output: 3585


🏁 Script executed:

#!/bin/bash
# Look for API setup and middleware registration
rg -n 'app\.use|middleware|bodyParams|queryParams' apps/meteor/app/api/server/ApiClass.ts -B2 -A3 -t ts | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 1964


🏁 Script executed:

#!/bin/bash
# Check how the HTTP router is initialized
rg -n 'new Router|createRouter|setupRouter' apps/meteor/app/api/server/ -B2 -A5 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 5860


🏁 Script executed:

#!/bin/bash
# Search for where RocketChatAPIRouter is instantiated
rg -n 'new RocketChatAPIRouter|RocketChatAPIRouter' apps/meteor/app/api/server/ -B2 -A5 -t ts | head -80

Repository: RocketChat/Rocket.Chat

Length of output: 4629


🏁 Script executed:

#!/bin/bash
# Look at the full ApiClass initialization
rg -n 'constructor|initRoutes|initialize' apps/meteor/app/api/server/ApiClass.ts -B1 -A8 -t ts | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 1018


🏁 Script executed:

#!/bin/bash
# Search for where body/query parsing happens - check imports and setup
head -100 apps/meteor/app/api/server/ApiClass.ts

Repository: RocketChat/Rocket.Chat

Length of output: 4155


🏁 Script executed:

#!/bin/bash
# Look at api.ts to see middleware registration
cat -n apps/meteor/app/api/server/api.ts | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 4643


🏁 Script executed:

#!/bin/bash
# Search for where body/query params are extracted or middleware that sets them
rg -n 'use\(|middleware|setBodyParams|setQueryParams|c\.set\(' apps/meteor/app/api/server/ -t ts | grep -v spec | grep -v test | head -40

Repository: RocketChat/Rocket.Chat

Length of output: 1748


🏁 Script executed:

#!/bin/bash
# Look for the http-router package to understand how it works
rg -n 'bodyParams|queryParams|c\.get' apps/meteor/app/api/server/middlewares/ -t ts -B2 -A2

Repository: RocketChat/Rocket.Chat

Length of output: 540


🏁 Script executed:

#!/bin/bash
# Look at remoteAddressMiddleware to understand the pattern
cat -n apps/meteor/app/api/server/middlewares/remoteAddressMiddleware.ts

Repository: RocketChat/Rocket.Chat

Length of output: 1553


🏁 Script executed:

#!/bin/bash
# Search for where bodyParams and queryParams are actually set
rg -n "set\('bodyParams'|set\('queryParams'|bodyParams.*=|queryParams.*=" apps/meteor/app/api/server/ -B3 -A3 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 18487


🏁 Script executed:

#!/bin/bash
# Check if http-router package might be handling this - search for getBodyParams or similar
rg -n "getBodyParams|getQueryParams|body.*parse|query.*parse" apps/meteor/app/api/server/ -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 4187


🏁 Script executed:

#!/bin/bash
# Look at the router spec to see if it shows how params are set
cat -n apps/meteor/app/api/server/router.spec.ts | head -120

Repository: RocketChat/Rocket.Chat

Length of output: 1935


🏁 Script executed:

#!/bin/bash
# Search for any use method that might set params
rg -n '\.use\(' apps/meteor/app/api/server/router.ts apps/meteor/app/api/server/ApiClass.ts -B3 -A8 -t ts

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Look for where body or query might be extracted - check the Router parent class behavior
rg -n 'req\.(body|query)' apps/meteor/app/api/server/ -t ts | head -20

Repository: RocketChat/Rocket.Chat

Length of output: 185


🏁 Script executed:

#!/bin/bash
# Check http-router imports and documentation or check if there's a way params get set
find . -name "*.json" -path "*/node_modules/@rocket.chat/http-router/*" 2>/dev/null | head -5

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Look for explicit middleware that parses request bodies
rg -n 'bodyParams.*set|set.*bodyParams|queryParams.*set|set.*queryParams' apps/meteor/app/ -t ts -B3 -A3

Repository: RocketChat/Rocket.Chat

Length of output: 50378


🏁 Script executed:

#!/bin/bash
# Look at authentication middleware
cat -n apps/meteor/app/api/server/middlewares/authentication.ts

Repository: RocketChat/Rocket.Chat

Length of output: 2545


🏁 Script executed:

#!/bin/bash
# Search for where `@rocket.chat/http-router` might be used to understand param parsing
rg -n "req.query|req.body|c.req" apps/meteor/app/api/server/ -t ts | head -30

Repository: RocketChat/Rocket.Chat

Length of output: 2068


Add defensive defaults for potentially undefined bodyParams and queryParams.

The HonoContext type system declares bodyParams and queryParams as non-optional Record<string, unknown>, but c.get() can return undefined if these values are not set upstream. While the codebase assumes they're always objects (evidenced by widespread destructuring without null checks), adding ?? {} guards against potential runtime errors if the upstream middleware in @rocket.chat/http-router fails to set these values.

✅ Safer default for missing params
-				queryParams: c.get('queryParams'),
-				bodyParams: c.get('bodyParams'),
+				queryParams: c.get('queryParams') ?? {},
+				bodyParams: c.get('bodyParams') ?? {},

Regarding application/x-www-form-urlencoded requests with payload={...} (Slack/GitHub style): This unwrapping logic is not visible in the codebase and is likely handled by the @rocket.chat/http-router package. There is no evidence that this handling is missing or broken by the refactoring.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const context: APIActionContext = {
requestIp: c.get('remoteAddress'),
urlParams: req.param(),
queryParams,
bodyParams,
queryParams: c.get('queryParams'),
bodyParams: c.get('bodyParams'),
request,
const context: APIActionContext = {
requestIp: c.get('remoteAddress'),
urlParams: req.param(),
queryParams: c.get('queryParams') ?? {},
bodyParams: c.get('bodyParams') ?? {},
request,
🤖 Prompt for AI Agents
In `@apps/meteor/app/api/server/router.ts` around lines 44 - 49, The
APIActionContext construction should defensively default potentially-undefined
context entries; update the code that builds APIActionContext (the object with
requestIp, urlParams, queryParams, bodyParams, request) to use
c.get('bodyParams') ?? {} and c.get('queryParams') ?? {} so bodyParams and
queryParams are always objects even if c.get(...) returns undefined, keeping the
existing fields (e.g., requestIp: c.get('remoteAddress') and urlParams:
req.param()) unchanged.

@ricardogarim ricardogarim force-pushed the chore/router-improvements branch 2 times, most recently from 3ad9b41 to 5ffad11 Compare January 23, 2026 21:36
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.

5 participants