Skip to content

🐛(backend) support unencoded S3 notification object keys#1455

Merged
lebaudantoine merged 5 commits into
suitenumerique:mainfrom
agasurfer:fix/s3parser-urlencode
Jul 2, 2026
Merged

🐛(backend) support unencoded S3 notification object keys#1455
lebaudantoine merged 5 commits into
suitenumerique:mainfrom
agasurfer:fix/s3parser-urlencode

Conversation

@agasurfer

Copy link
Copy Markdown

Purpose

Fixes #1454.

Some S3-compatible storage providers, such as Ceph RGW, send notification object keys with raw path separators:

recordings/<recording-id>.mp4

However, the recording event parser currently expects URL-encoded separators:

recordings%2F<recording-id>.mp4

As a result, valid storage notifications are ignored, recordings remain in the stopped state, and notification emails are not sent.

This pull request normalizes S3 notification object keys before filepath validation while preserving already encoded separators.

Changes

  • URL-encode raw S3 notification object keys before filepath validation.
  • Preserve existing percent-encoded sequences to avoid converting %2F into %252F.
  • Add tests for both raw and already encoded object keys.

Testing

Verified that the parser accepts both:

recordings/<recording-id>.mp4
recordings%2F<recording-id>.mp4

Before this change, the first representation raised InvalidFilepathError.

@lebaudantoine

Copy link
Copy Markdown
Collaborator

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@greptile-apps

greptile-apps Bot commented Jun 29, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge — the change is minimal and correctly normalises S3 object keys for both raw and pre-encoded formats.

The normalization logic is correct: safe="%+" prevents double-encoding of already-encoded sequences and preserves + signs, the regex still matches after encoding, and mimetypes.guess_type is unaffected since the file extension is always at the end of the key. The new tests cover the three relevant cases cleanly.

No files require special attention.

Important Files Changed

Filename Overview
src/backend/core/recording/event/parsers.py Adds quote(filepath, safe="%+") in S3Parser.parse() to normalize raw-slash S3 keys before validation; MinioParser unchanged (pre-existing gap already flagged in a prior review).
src/backend/core/tests/recording/event/test_parsers.py Adds three new S3 parser tests covering already-encoded keys, raw-slash keys, and plus-sign preservation — good coverage for the new normalization path.
CHANGELOG.md Adds changelog entry for the bug fix.

Reviews (6): Last reviewed commit: "✅(backend) cover encoded S3 keys with pl..." | Re-trigger Greptile

Comment thread src/backend/core/recording/event/parsers.py Outdated
Comment thread src/backend/core/recording/event/parsers.py Outdated
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Failed to post review comments.

We encountered an issue with GitHub. Use @coderabbitai full review to retry the review.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2859aec8-d2e2-4e1e-b12d-ccb131a8d32c

📥 Commits

Reviewing files that changed from the base of the PR and between 1523e6a and 7cf71de.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/backend/core/recording/event/parsers.py
  • src/backend/core/tests/recording/event/test_parsers.py

Walkthrough

S3Parser.parse in parsers.py now imports quote_plus and applies it to the raw S3 object key (with safe="%") before constructing the StorageEvent filepath. This normalizes both already-encoded and unencoded S3 notification keys. Two new tests cover each case. The changelog records the addition.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main backend change: supporting unencoded S3 notification object keys.
Description check ✅ Passed The description matches the patch and explains the compatibility fix and tests.
Linked Issues check ✅ Passed The parser now normalizes raw S3 keys and tests cover raw and encoded forms, satisfying the linked issue's compatibility requirement.
Out of Scope Changes check ✅ Passed The changelog note is directly related to the parser fix, and no unrelated code changes are evident.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/core/recording/event/parsers.py`:
- Around line 168-169: The filepath normalization in BaseS3Parser is still
re-encoding valid S3 keys because quote_plus(..., safe="%") converts literal
plus signs in already-encoded prefixes, which breaks validate() matching. Update
the parsing logic in the relevant filepath handling so it preserves plus signs
as well as existing percent-encoded separators, or only normalizes the separator
without re-encoding the whole key. Add a regression test around
BaseS3Parser.validate() for an encoded key like recordings+folder%2F<id>.mp4 to
ensure this case still matches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2859aec8-d2e2-4e1e-b12d-ccb131a8d32c

📥 Commits

Reviewing files that changed from the base of the PR and between 1523e6a and 7cf71de.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/backend/core/recording/event/parsers.py
  • src/backend/core/tests/recording/event/test_parsers.py

Comment on lines +168 to +169
# Preserve already URL-encoded separators while encoding raw S3 object keys.
filepath = quote_plus(filepath, safe="%")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Parser outline =="
ast-grep outline src/backend/core/recording/event/parsers.py --view expanded || true

echo
echo "== Relevant parser slice =="
nl -ba src/backend/core/recording/event/parsers.py | sed -n '90,190p'

echo
echo "== Existing tests around S3 filepath normalization =="
nl -ba src/backend/core/tests/recording/event/test_parsers.py | sed -n '340,430p'

echo
echo "== Search for filepath regex / output folder encoding assumptions =="
rg -n -C3 'filepath_regex|RECORDING_OUTPUT_FOLDER|quote_plus|quote\(' src/backend/core src/backend/core/tests

Repository: suitenumerique/meet

Length of output: 1218


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== parser slice =="
sed -n '145,185p' src/backend/core/recording/event/parsers.py

echo
echo "== tests slice =="
sed -n '330,450p' src/backend/core/tests/recording/event/test_parsers.py

echo
echo "== quote_plus probe =="
python3 - <<'PY'
from urllib.parse import quote_plus
samples = [
    "recordings+folder%2Fid.mp4",
    "recordings folder%2Fid.mp4",
    "recordings%2Bfolder%2Fid.mp4",
    "recordings+folder/id.mp4",
]
for s in samples:
    print(s, "->", quote_plus(s, safe="%"))
PY

Repository: suitenumerique/meet

Length of output: 5445


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '80,145p' src/backend/core/recording/event/parsers.py

Repository: suitenumerique/meet

Length of output: 2634


Avoid re-encoding S3 keys here. quote_plus(..., safe="%") still turns already-encoded + into %2B, so valid notifications with spaces in a prefix stop matching BaseS3Parser.validate(). Preserve + as well, or normalize only the separator, and add a regression test for an encoded key like recordings+folder%2F<id>.mp4.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/core/recording/event/parsers.py` around lines 168 - 169, The
filepath normalization in BaseS3Parser is still re-encoding valid S3 keys
because quote_plus(..., safe="%") converts literal plus signs in already-encoded
prefixes, which breaks validate() matching. Update the parsing logic in the
relevant filepath handling so it preserves plus signs as well as existing
percent-encoded separators, or only normalizes the separator without re-encoding
the whole key. Add a regression test around BaseS3Parser.validate() for an
encoded key like recordings+folder%2F<id>.mp4 to ensure this case still matches.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done. I switched the normalization to preserve + as well as existing percent-encoded separators, and added a regression test for an already encoded S3 key with a + in the prefix.

It verifies that valid notifications with spaces encoded as + keep matching BaseS3Parser.validate().

@agasurfer agasurfer requested a review from lebaudantoine June 30, 2026 08:57
@lebaudantoine

Copy link
Copy Markdown
Collaborator

let's connect on matrix https://matrix.to/#/#meet-official:matrix.org

ilias added 5 commits July 2, 2026 11:48
Add docstrings to the S3 parser tests
Correction to preserve already encoded plus signs in addition to slashes.
Add a regression test for already encoded S3 notification keys that contain plus signs in the prefix.
@lebaudantoine lebaudantoine force-pushed the fix/s3parser-urlencode branch from 544941b to 735b4cd Compare July 2, 2026 09:51
@sonarqubecloud

sonarqubecloud Bot commented Jul 2, 2026

Copy link
Copy Markdown

@lebaudantoine lebaudantoine merged commit 27dce44 into suitenumerique:main Jul 2, 2026
23 of 24 checks passed
@agasurfer agasurfer deleted the fix/s3parser-urlencode branch July 3, 2026 07:59
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.

S3Parser ignores Ceph notifications when object keys contain unencoded slashes

2 participants