fix: resolve document ID conflicts with URL encoding
- Fixed document ID conflicts caused by unencoded slashes in mailbox names - Added URL encoding for all document IDs used in CouchDB REST API calls - Mailbox names with slashes (e.g., 'Work/Projects') now create proper document IDs - Resolves issue where 'Work/Projects_1' was incorrectly stored as document 'Work' with attachment 'Projects_1' - Added urlencoding dependency for proper URL-safe document ID handling All messages now store successfully without conflicts across all mailboxes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d4e10a3aae
commit
fbc8ebbbdf
2 changed files with 20 additions and 9 deletions
|
|
@ -52,6 +52,9 @@ dirs = "5.0"
|
|||
# Pattern matching for folder filters
|
||||
glob = "0.3"
|
||||
|
||||
# URL encoding for document IDs
|
||||
urlencoding = "2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
# Testing utilities
|
||||
tokio-test = "0.4"
|
||||
|
|
|
|||
|
|
@ -187,7 +187,8 @@ impl CouchClient {
|
|||
}
|
||||
|
||||
self.retry_operation("store_mail_document", || async {
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(&doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.put(&url).json(&document);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -229,7 +230,9 @@ impl CouchClient {
|
|||
let rev = doc_response.ok_or_else(|| anyhow!("Document {} not found", doc_id))?;
|
||||
|
||||
// Upload the attachment
|
||||
let url = format!("{}/{}/{}/{}?rev={}", self.base_url, db_name, doc_id, attachment_name, rev);
|
||||
let encoded_doc_id = urlencoding::encode(doc_id);
|
||||
let encoded_attachment_name = urlencoding::encode(attachment_name);
|
||||
let url = format!("{}/{}/{}/{}?rev={}", self.base_url, db_name, encoded_doc_id, encoded_attachment_name, rev);
|
||||
let mut request = self.client
|
||||
.put(&url)
|
||||
.header("Content-Type", content_type)
|
||||
|
|
@ -255,7 +258,8 @@ impl CouchClient {
|
|||
|
||||
/// Get document revision
|
||||
async fn get_document_rev(&self, db_name: &str, doc_id: &str) -> Result<Option<String>> {
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.get(&url);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -287,7 +291,8 @@ impl CouchClient {
|
|||
metadata_to_store.rev = existing.rev;
|
||||
}
|
||||
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.put(&url).json(&metadata_to_store);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -311,7 +316,8 @@ impl CouchClient {
|
|||
/// Get sync metadata for a mailbox
|
||||
pub async fn get_sync_metadata(&self, db_name: &str, mailbox: &str) -> Result<SyncMetadata> {
|
||||
let doc_id = format!("sync_metadata_{}", mailbox);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(&doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.get(&url);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -337,7 +343,8 @@ impl CouchClient {
|
|||
|
||||
/// Check if a document exists
|
||||
pub async fn document_exists(&self, db_name: &str, doc_id: &str) -> Result<bool> {
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.head(&url);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -414,7 +421,8 @@ impl CouchClient {
|
|||
/// Delete a document (used in sync mode for deleted messages)
|
||||
pub async fn delete_document(&self, db_name: &str, doc_id: &str) -> Result<()> {
|
||||
// First get the document to get its revision
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, doc_id);
|
||||
let encoded_doc_id = urlencoding::encode(doc_id);
|
||||
let url = format!("{}/{}/{}", self.base_url, db_name, encoded_doc_id);
|
||||
let mut request = self.client.get(&url);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
@ -432,7 +440,7 @@ impl CouchClient {
|
|||
.ok_or_else(|| anyhow!("Document {} has no _rev field", doc_id))?;
|
||||
|
||||
// Now delete the document
|
||||
let delete_url = format!("{}/{}/{}?rev={}", self.base_url, db_name, doc_id, rev);
|
||||
let delete_url = format!("{}/{}/{}?rev={}", self.base_url, db_name, encoded_doc_id, rev);
|
||||
let mut delete_request = self.client.delete(&delete_url);
|
||||
|
||||
if let Some((username, password)) = &self.auth {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue