Skip to content

fix(synology-chat): support JSON/alias payloads and ACK webhook with 204#26635

Merged
steipete merged 2 commits intoopenclaw:mainfrom
memphislee09-source:fix/synology-webhook-payload-compat-ack
Mar 2, 2026
Merged

fix(synology-chat): support JSON/alias payloads and ACK webhook with 204#26635
steipete merged 2 commits intoopenclaw:mainfrom
memphislee09-source:fix/synology-webhook-payload-compat-ack

Conversation

@memphislee09-source
Copy link
Contributor

@memphislee09-source memphislee09-source commented Feb 25, 2026

Summary

Fixes a Synology Chat webhook interoperability issue that can leave users stuck on Processing....

This patch updates the Synology webhook handler to:

  • accept both application/x-www-form-urlencoded and application/json
  • normalize token from body.token, query.token, or headers
  • support payload aliases:
    • user_id <- user_id | userId | user
    • text <- text | message | content
  • ACK webhook requests with 204 No Content instead of returning {"text":"Processing..."}

Why

In real Synology setups, outgoing webhook payload shape/content-type can vary. Strict body-only form parsing caused missing-field errors and UI stalls.

Implementation notes

  • Added robust normalization helpers in webhook-handler.ts
  • Added query/header token extraction support
  • Kept async deliver + outgoing reply path unchanged
  • Updated/extended tests to cover JSON + aliases + query/header token behavior

Tests

  • pnpm vitest run extensions/synology-chat/src/webhook-handler.test.ts

Closes #26628

Greptile Summary

This PR improves the Synology Chat webhook handler to accept both application/json and application/x-www-form-urlencoded payloads, support field aliases (userId/user, message/content), resolve tokens from body, query params, or headers, and ACK requests with 204 No Content instead of a 200 with {"text":"Processing..."} that could stall the Synology Chat UI.

  • Payload flexibility: Adds JSON parsing, content-type sniffing fallback, and field alias resolution — well-suited for the variety of Synology Chat outgoing webhook configurations in the wild
  • Token resolution: Token can now come from body, query string, or custom/Authorization headers, with body taking priority
  • 204 ACK: Prevents the Synology Chat UI from displaying a permanent "Processing..." indicator by acknowledging immediately with no body
  • Non-Bearer fallback concern: extractTokenFromHeaders falls back to using the raw Authorization header value (including scheme prefix) as the token when it doesn't match Bearer. This should return undefined instead to avoid masking misconfigurations
  • Tests: Good coverage added for JSON payloads, alias fields, query token, and header token paths

Confidence Score: 4/5

  • This PR is safe to merge with one minor issue to address in the header token extraction fallback.
  • The changes are well-structured with clean helper functions, proper error handling, and good test coverage. The 204 ACK pattern is the right fix for the Synology Chat UI stall. The one flagged issue (non-Bearer Authorization header fallback) is not a security vulnerability since token validation will reject mismatched values, but it could mask configuration errors. The rest of the implementation follows sound patterns.
  • extensions/synology-chat/src/webhook-handler.ts — review the extractTokenFromHeaders non-Bearer fallback on line 108

Last reviewed commit: d660156

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +106 to +108
const bearerMatch = auth.match(/^Bearer\s+(.+)$/i);
if (bearerMatch?.[1]) return bearerMatch[1].trim();
return auth.trim();
Copy link
Contributor

Choose a reason for hiding this comment

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

Non-Bearer auth header used as raw token

When the Authorization header is present but uses a scheme other than Bearer (e.g. Basic dXNlcjpwYXNz), the entire header value (including the scheme prefix like Basic ) is used as the token. This will silently fail validateToken — which is safe — but it's surprising behavior that could mask configuration mistakes. Consider returning undefined when the header doesn't match the Bearer pattern instead of falling back to the raw value:

Suggested change
const bearerMatch = auth.match(/^Bearer\s+(.+)$/i);
if (bearerMatch?.[1]) return bearerMatch[1].trim();
return auth.trim();
const bearerMatch = auth.match(/^Bearer\s+(.+)$/i);
if (bearerMatch?.[1]) return bearerMatch[1].trim();
return undefined;

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/synology-chat/src/webhook-handler.ts
Line: 106-108

Comment:
**Non-Bearer auth header used as raw token**

When the `Authorization` header is present but uses a scheme other than `Bearer` (e.g. `Basic dXNlcjpwYXNz`), the entire header value (including the scheme prefix like `Basic `) is used as the token. This will silently fail `validateToken` — which is safe — but it's surprising behavior that could mask configuration mistakes. Consider returning `undefined` when the header doesn't match the `Bearer` pattern instead of falling back to the raw value:

```suggestion
  const bearerMatch = auth.match(/^Bearer\s+(.+)$/i);
  if (bearerMatch?.[1]) return bearerMatch[1].trim();
  return undefined;
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@steipete steipete force-pushed the fix/synology-webhook-payload-compat-ack branch from d660156 to aa42241 Compare March 2, 2026 19:45
@steipete steipete merged commit 2a2e2c3 into openclaw:main Mar 2, 2026
@steipete
Copy link
Contributor

steipete commented Mar 2, 2026

Landed via temp rebase onto main.

  • Gate: pnpm vitest run extensions/synology-chat/src/webhook-handler.test.ts extensions/synology-chat/src/channel.integration.test.ts --maxWorkers=1
  • Land commit: aa42241be0d26f72db4b028ca95b7ce6bda8aca0
  • Merge commit: 2a2e2c3

Thanks @memphislee09-source!

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Synology Chat outgoing webhook can get stuck on Processing due to strict payload parsing

2 participants