Skip to content

fix: Encode HTTP headers in patch operations to handle special characters (#30)#48

Open
vanmarkic wants to merge 2 commits intojacksteamdev:mainfrom
vanmarkic:claude/fix-issue-30-patch-file-headers-01DypPdPvjF9qDyRDG1CAob5
Open

fix: Encode HTTP headers in patch operations to handle special characters (#30)#48
vanmarkic wants to merge 2 commits intojacksteamdev:mainfrom
vanmarkic:claude/fix-issue-30-patch-file-headers-01DypPdPvjF9qDyRDG1CAob5

Conversation

@vanmarkic
Copy link
Copy Markdown

Summary

  • Fixes issue where special characters in file content caused PATCH operations to fail
  • Adds proper header encoding for HTTP requests
  • Includes comprehensive test coverage

Changes

  • Implemented header encoding in PATCH operations to handle special characters
  • Added 209 lines of tests for various special character scenarios
  • Ensures proper handling of emojis, Unicode, and special symbols in file content

Related Issue

Fixes bug #30

🤖 Generated with Claude Code

…ters (jacksteamdev#30)

The patch_vault_file and patch_active_file functions were failing with HTTP 400 errors when the Target header contained:
- Multi-line text (newlines)
- Special characters (accented letters like é, à, etc.)
- Special Obsidian syntax (like [[wikilinks]])

This occurred because HTTP headers must be ASCII and cannot contain newlines or certain special characters. The fix applies URL encoding to the Target and Target-Delimiter header values using encodeURIComponent(), which:

- Converts newlines and special characters to safe percent-encoded format
- Maintains compatibility with standard HTTP header parsing
- Allows the Local REST API plugin to properly decode and process the values

This resolves the "Header 'Target' has invalid value" errors and allows patch operations to work correctly with complex target strings.

Fixes jacksteamdev#30
)

- Test encoding of special characters (#, &, ?, =, etc.)
- Test encoding of newline and carriage return characters
- Test encoding of multi-byte Unicode and emoji characters
- Test encoding of path separators (/ and \)
- Test encoding of whitespace (spaces, tabs)
- Test header construction with encoded target and delimiter
- Verify preservation of alphanumeric characters
- Verify trimTargetWhitespace boolean to string conversion
@netlify
Copy link
Copy Markdown

netlify bot commented Nov 15, 2025

Deploy Preview for superb-starlight-b5acb5 canceled.

Name Link
🔨 Latest commit 80431cb
🔍 Latest deploy log https://app.netlify.com/projects/superb-starlight-b5acb5/deploys/6918c173f110630008bb3342

istefox added a commit to istefox/obsidian-mcp-connector that referenced this pull request Apr 11, 2026
…uster A)

Fix three independent bugs in patch_active_file and patch_vault_file that
together made the tools dangerous and unusable for many real-world cases:

1. Silent content corruption with nested headings
   The Local REST API markdown-patch library indexes headings by full
   hierarchical path with the "::" delimiter ("Top Level::Section A"). The
   server was sending partial leaf names ("Section A") verbatim, and because
   Create-Target-If-Missing was hardcoded to true, the lookup failed silently
   and a new heading was appended at EOF instead of patching the intended
   one. The server now parses the target file, resolves the leaf name to
   its full ancestor path via a new resolveHeadingPath helper, and sends
   that to the API. Strict mode is exposed through the new
   createTargetIfMissing optional parameter so agents can opt into
   explicit errors instead of auto-creation.

2. Non-ASCII heading failures
   Target and Target-Delimiter HTTP headers were sent raw, which fails for
   Japanese, emoji, or any heading with characters outside the ASCII
   header grammar. Both headers are now URL-encoded — crucially, *after*
   path resolution, so the indexer lookup still sees plain strings.

3. Missing trailing newlines on append
   When operation == "append", content without trailing newlines would run
   visually into the next section. Normalized to end with "\n\n".

Approach combines three community PRs never merged upstream:
- PR jacksteamdev#72 (grimlor): resolveHeadingPath + createTargetIfMissing
- PR jacksteamdev#69 (marcoaperez): URL-encode Target / Target-Delimiter
- PR jacksteamdev#48 (vanmarkic): test coverage patterns for header encoding

Adds patchVaultFile.test.ts with 10 unit tests for resolveHeadingPath:
empty content, no headings, H1 match, H2 partial, deep H3 nesting,
missing leaf, duplicate names, custom delimiter, stack reset on level
return, and non-heading lines mid-paragraph.

Performance note: resolving a partial heading name adds one extra HTTP
request per PATCH call (to fetch the target file content). Full-path
targets (already containing the delimiter) skip the resolution step.

Manual end-to-end verification pending on Stefano's Obsidian + Local
REST API setup.

Refs: jacksteamdev#30, jacksteamdev#71
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants