Skip to content

Commit b94a2e5

Browse files
committed
feat: add detail errors handler
1 parent 8cb565f commit b94a2e5

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

src/filestation/synology_filestation.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import tempfile
88
import json
9+
import unicodedata
910

1011

1112
class SynologyFileStation:
@@ -16,7 +17,7 @@ def __init__(self, base_url: str, session_id: str):
1617
self.session_id = session_id
1718
self.api_url = f"{self.base_url}/webapi/entry.cgi"
1819

19-
def _make_request(self, api: str, version: str, method: str, **params) -> Dict[str, Any]:
20+
def _make_request(self, api: str, version: str, method: str, use_post: bool = False, **params) -> Dict[str, Any]:
2021
"""Make a request to Synology API."""
2122
request_params = {
2223
'api': api,
@@ -26,13 +27,36 @@ def _make_request(self, api: str, version: str, method: str, **params) -> Dict[s
2627
**params
2728
}
2829

29-
response = requests.get(self.api_url, params=request_params)
30+
if use_post:
31+
# For POST requests, ensure UTF-8 encoding for Unicode characters
32+
response = requests.post(
33+
self.api_url,
34+
data=request_params,
35+
headers={'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
36+
)
37+
else:
38+
response = requests.get(self.api_url, params=request_params)
3039
response.raise_for_status()
3140

3241
data = response.json()
3342
if not data.get('success'):
3443
error_code = data.get('error', {}).get('code', 'unknown')
35-
raise Exception(f"Synology API error: {error_code}")
44+
error_info = data.get('error', {})
45+
46+
# Include detailed error information if available
47+
error_message = f"Synology API error: {error_code}"
48+
49+
# Check for detailed errors array as mentioned in documentation
50+
if 'errors' in error_info and error_info['errors']:
51+
detailed_errors = []
52+
for err in error_info['errors']:
53+
err_detail = f"Code {err.get('code', 'unknown')}"
54+
if 'path' in err:
55+
err_detail += f" for path: {err['path']}"
56+
detailed_errors.append(err_detail)
57+
error_message += f" - Details: {'; '.join(detailed_errors)}"
58+
59+
raise Exception(error_message)
3660

3761
return data.get('data', {})
3862

@@ -62,6 +86,9 @@ def _format_path(self, path: str) -> str:
6286
path = '/' + path
6387
if path != '/' and path.endswith('/'):
6488
path = path.rstrip('/')
89+
90+
# Normalize Unicode characters to NFC form (most common for filesystems)
91+
path = unicodedata.normalize('NFC', path)
6592
return path
6693

6794
def list_shares(self) -> List[Dict[str, Any]]:
@@ -248,11 +275,20 @@ def rename_file(self, path: str, new_name: str) -> Dict[str, Any]:
248275
if not new_name:
249276
raise Exception("Invalid new name")
250277

251-
# Use the rename API
278+
# According to official Synology API docs, path and name must be JSON arrays even for single values
279+
# The parameters should be formatted as: path=["/path"] and name=["name"]
280+
# Let requests library handle URL encoding automatically
281+
282+
# Create JSON arrays without manual URL encoding - let requests handle it
283+
path_array = json.dumps([formatted_path])
284+
name_array = json.dumps([new_name])
285+
286+
# Use GET request as specified in official documentation
252287
data = self._make_request(
253288
'SYNO.FileStation.Rename', '2', 'rename',
254-
path=formatted_path,
255-
name=new_name
289+
use_post=False, # Official docs specify GET
290+
path=path_array,
291+
name=name_array
256292
)
257293

258294
# Get the parent directory path

0 commit comments

Comments
 (0)