Skip to content

Commit 6fb9bb1

Browse files
authored
Consolidate error responses (#8264)
2 parents 2ea266c + 67750fd commit 6fb9bb1

36 files changed

+287
-169
lines changed

src/tribler/core/content_discovery/restapi/search_endpoint.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,16 @@ async def remote_search(self, request: RequestType) -> RESTResponse:
7575
try:
7676
sanitized = DatabaseEndpoint.sanitize_parameters(request.query)
7777
except (ValueError, KeyError) as e:
78-
return RESTResponse({"error": f"Error processing request parameters: {e}"}, status=HTTP_BAD_REQUEST)
78+
return RESTResponse({"error": {
79+
"handled": True,
80+
"message": f"Error processing request parameters: {e}"
81+
}}, status=HTTP_BAD_REQUEST)
7982
query = request.query.get("fts_text")
8083
if query is None:
81-
return RESTResponse({"error": f"Got search with no fts_text: {dict(request.query)}"},
84+
return RESTResponse({"error": {
85+
"handled": True,
86+
"message": f"Got search with no fts_text: {dict(request.query)}"
87+
}},
8288
status=HTTP_BAD_REQUEST)
8389
if t_filter := request.query.get("filter"):
8490
query += f" {t_filter}"

src/tribler/core/database/restapi/database_endpoint.py

+20-6
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ async def get_torrent_health(self, request: RequestType) -> RESTResponse:
184184
try:
185185
timeout = int(request.query.get("timeout", TORRENT_CHECK_TIMEOUT))
186186
except ValueError as e:
187-
return RESTResponse({"error": f"Error processing timeout parameter: {e}"}, status=HTTP_BAD_REQUEST)
187+
return RESTResponse({"error": {
188+
"handled": True,
189+
"message": f"Error processing timeout parameter: {e}"
190+
}}, status=HTTP_BAD_REQUEST)
188191

189192
if self.torrent_checker is None:
190193
return RESTResponse({"checking": False})
@@ -270,16 +273,24 @@ async def local_search(self, request: RequestType) -> RESTResponse: # noqa: C90
270273
sanitized = self.sanitize_parameters(request.query)
271274
tags = sanitized.pop("tags", None)
272275
except (ValueError, KeyError):
273-
return RESTResponse({"error": "Error processing request parameters"}, status=HTTP_BAD_REQUEST)
276+
return RESTResponse({"error": {
277+
"handled": True,
278+
"message": "Error processing request parameters"
279+
}}, status=HTTP_BAD_REQUEST)
274280

275281
if self.tribler_db is None:
276-
return RESTResponse({"error": "Tribler DB not initialized"}, status=HTTP_NOT_FOUND)
282+
return RESTResponse({"error": {
283+
"handled": True,
284+
"message": "Tribler DB not initialized"
285+
}}, status=HTTP_NOT_FOUND)
277286

278287
include_total = request.query.get("include_total", "")
279288
query = request.query.get("fts_text")
280289
if query is None:
281-
return RESTResponse({"error": f"Got search with no fts_text: {dict(request.query)}"},
282-
status=HTTP_BAD_REQUEST)
290+
return RESTResponse({"error": {
291+
"handled": True,
292+
"message": f"Got search with no fts_text: {dict(request.query)}"
293+
}}, status=HTTP_BAD_REQUEST)
283294
if t_filter := request.query.get("filter"):
284295
query += f" {t_filter}"
285296
fts = to_fts_query(query)
@@ -354,7 +365,10 @@ async def completions(self, request: RequestType) -> RESTResponse:
354365
"""
355366
args = request.query
356367
if "q" not in args:
357-
return RESTResponse({"error": "query parameter missing"}, status=HTTP_BAD_REQUEST)
368+
return RESTResponse({"error": {
369+
"handled": True,
370+
"message": "query parameter missing"
371+
}}, status=HTTP_BAD_REQUEST)
358372

359373
keywords = args["q"].strip().lower()
360374
results = request.context[0].get_auto_complete_terms(keywords, max_terms=5)

src/tribler/core/knowledge/restapi/knowledge_endpoint.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,15 @@ def validate_infohash(infohash: str) -> tuple[bool, RESTResponse | None]:
6363
"""
6464
try:
6565
if len(infohash) != 40:
66-
return False, RESTResponse({"error": "Invalid infohash"}, status=HTTP_BAD_REQUEST)
66+
return False, RESTResponse({"error": {
67+
"handled": True,
68+
"message": "Invalid infohash"
69+
}}, status=HTTP_BAD_REQUEST)
6770
except binascii.Error:
68-
return False, RESTResponse({"error": "Invalid infohash"}, status=HTTP_BAD_REQUEST)
71+
return False, RESTResponse({"error": {
72+
"handled": True,
73+
"message": "Invalid infohash"
74+
}}, status=HTTP_BAD_REQUEST)
6975

7076
return True, None
7177

@@ -77,7 +83,8 @@ def validate_infohash(infohash: str) -> tuple[bool, RESTResponse | None]:
7783
"schema": schema(UpdateTagsResponse={"success": Boolean()})
7884
},
7985
HTTP_BAD_REQUEST: {
80-
"schema": HandledErrorSchema, "example": {"error": "Invalid tag length"}},
86+
"schema": HandledErrorSchema, "example": {"error": {"handled": True, "message": "Invalid tag length"}}
87+
}
8188
},
8289
description="This endpoint updates a particular torrent with the provided metadata."
8390
)
@@ -97,7 +104,10 @@ async def update_knowledge_entries(self, request: RequestType) -> RESTResponse:
97104
for statement in params["statements"]:
98105
obj = statement["object"]
99106
if not is_valid_resource(obj):
100-
return RESTResponse({"error": "Invalid tag length"}, status=HTTP_BAD_REQUEST)
107+
return RESTResponse({"error": {
108+
"handled": True,
109+
"message": "Invalid tag length"
110+
}}, status=HTTP_BAD_REQUEST)
101111

102112
statements.append(statement)
103113

@@ -146,7 +156,8 @@ def modify_statements(self, db: TriblerDatabase, infohash: str, statements: list
146156
"schema": schema(SuggestedTagsResponse={"suggestions": List(String)})
147157
},
148158
HTTP_BAD_REQUEST: {
149-
"schema": HandledErrorSchema, "example": {"error": "Invalid infohash"}},
159+
"schema": HandledErrorSchema, "example": {"error": {"handled": True, "message": "Invalid infohash"}}
160+
}
150161
},
151162
description="This endpoint updates a particular torrent with the provided tags."
152163
)

src/tribler/core/libtorrent/restapi/create_torrent_endpoint.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def __init__(self, download_manager: DownloadManager, client_max_size: int = MAX
7575
},
7676
HTTP_BAD_REQUEST: {
7777
"schema": HandledErrorSchema,
78-
"examples": {"Error": {"error": "files parameter missing"}}
78+
"examples": {"Error": {"error": {"handled": True, "message": "files parameter missing"}}}
7979
}
8080
}
8181
)
@@ -96,7 +96,10 @@ async def create_torrent(self, request: Request) -> RESTResponse:
9696
if parameters.get("files"):
9797
file_path_list = [Path(p) for p in parameters["files"]]
9898
else:
99-
return RESTResponse({"error": "files parameter missing"}, status=HTTP_BAD_REQUEST)
99+
return RESTResponse({"error": {
100+
"handled": True,
101+
"message": "files parameter missing"
102+
}}, status=HTTP_BAD_REQUEST)
100103

101104
if parameters.get("description"):
102105
params["comment"] = parameters["description"]

src/tribler/core/libtorrent/restapi/downloads_endpoint.py

+76-21
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ def return_404(message: str = "this download does not exist") -> RESTResponse:
9292
"""
9393
Returns a 404 response code if your channel has not been created.
9494
"""
95-
return RESTResponse({"error": message}, status=HTTP_NOT_FOUND)
95+
return RESTResponse({"error": {
96+
"handled": True,
97+
"message": message
98+
}}, status=HTTP_NOT_FOUND)
9699

97100
def create_dconfig_from_params(self, parameters: dict) -> tuple[DownloadConfig, None] | tuple[None, str]:
98101
"""
@@ -423,19 +426,28 @@ async def add_download(self, request: Request) -> RESTResponse: # noqa: C901
423426
params = await request.json()
424427
uri = params.get("uri")
425428
if not uri:
426-
return RESTResponse({"error": "uri parameter missing"}, status=HTTP_BAD_REQUEST)
429+
return RESTResponse({"error": {
430+
"handled": True,
431+
"message": "uri parameter missing"
432+
}}, status=HTTP_BAD_REQUEST)
427433

428434
download_config, error = self.create_dconfig_from_params(params)
429435
if error:
430-
return RESTResponse({"error": error}, status=HTTP_BAD_REQUEST)
436+
return RESTResponse({"error": {
437+
"handled": True,
438+
"message": error
439+
}}, status=HTTP_BAD_REQUEST)
431440

432441
try:
433442
if tdef:
434443
download = await self.download_manager.start_download(tdef=tdef, config=download_config)
435444
elif uri:
436445
download = await self.download_manager.start_download_from_uri(uri, config=download_config)
437446
except Exception as e:
438-
return RESTResponse({"error": str(e)}, status=HTTP_INTERNAL_SERVER_ERROR)
447+
return RESTResponse({"error": {
448+
"handled": True,
449+
"message": str(e)
450+
}}, status=HTTP_INTERNAL_SERVER_ERROR)
439451

440452
return RESTResponse({"started": True, "infohash": hexlify(download.get_def().get_infohash()).decode()})
441453

@@ -465,7 +477,10 @@ async def delete_download(self, request: Request) -> RESTResponse:
465477
"""
466478
parameters = await request.json()
467479
if "remove_data" not in parameters:
468-
return RESTResponse({"error": "remove_data parameter missing"}, status=HTTP_BAD_REQUEST)
480+
return RESTResponse({"error": {
481+
"handled": True,
482+
"message": "remove_data parameter missing"
483+
}}, status=HTTP_BAD_REQUEST)
469484

470485
infohash = unhexlify(request.match_info["infohash"])
471486
download = self.download_manager.get_download(infohash)
@@ -514,8 +529,10 @@ async def update_download(self, request: Request) -> RESTResponse: # noqa: C901
514529

515530
parameters = await request.json()
516531
if len(parameters) > 1 and "anon_hops" in parameters:
517-
return RESTResponse({"error": "anon_hops must be the only parameter in this request"},
518-
status=HTTP_BAD_REQUEST)
532+
return RESTResponse({"error": {
533+
"handled": True,
534+
"message": "anon_hops must be the only parameter in this request"
535+
}}, status=HTTP_BAD_REQUEST)
519536
if 'anon_hops' in parameters:
520537
anon_hops = int(parameters['anon_hops'])
521538
try:
@@ -529,7 +546,10 @@ async def update_download(self, request: Request) -> RESTResponse: # noqa: C901
529546
selected_files_list = parameters["selected_files"]
530547
num_files = len(download.tdef.get_files())
531548
if not all(0 <= index < num_files for index in selected_files_list):
532-
return RESTResponse({"error": "index out of range"}, status=HTTP_BAD_REQUEST)
549+
return RESTResponse({"error": {
550+
"handled": True,
551+
"message": "index out of range"
552+
}}, status=HTTP_BAD_REQUEST)
533553
download.set_selected_files(selected_files_list)
534554

535555
if state := parameters.get("state"):
@@ -542,12 +562,17 @@ async def update_download(self, request: Request) -> RESTResponse: # noqa: C901
542562
elif state == "move_storage":
543563
dest_dir = Path(parameters["dest_dir"])
544564
if not dest_dir.exists():
545-
return RESTResponse({"error": f"Target directory ({dest_dir}) does not exist"},
546-
status=HTTP_BAD_REQUEST)
565+
return RESTResponse({"error": {
566+
"handled": True,
567+
"message": f"Target directory ({dest_dir}) does not exist"
568+
}}, status=HTTP_BAD_REQUEST)
547569
download.move_storage(dest_dir)
548570
download.checkpoint()
549571
else:
550-
return RESTResponse({"error": "unknown state parameter"}, status=HTTP_BAD_REQUEST)
572+
return RESTResponse({"error": {
573+
"handled": True,
574+
"message": "unknown state parameter"
575+
}}, status=HTTP_BAD_REQUEST)
551576

552577
return RESTResponse({"modified": True, "infohash": hexlify(download.get_def().get_infohash()).decode()})
553578

@@ -615,13 +640,19 @@ async def add_tracker(self, request: Request) -> RESTResponse:
615640
parameters = await request.json()
616641
url = parameters.get("url")
617642
if not url:
618-
return RESTResponse({"error": "url parameter missing"}, status=HTTP_BAD_REQUEST)
643+
return RESTResponse({"error": {
644+
"handled": True,
645+
"message": "url parameter missing"
646+
}}, status=HTTP_BAD_REQUEST)
619647

620648
try:
621649
download.add_trackers([url])
622650
download.handle.force_reannounce(0, len(download.handle.trackers()) - 1)
623651
except RuntimeError as e:
624-
return RESTResponse({"error": str(e)}, status=HTTP_INTERNAL_SERVER_ERROR)
652+
return RESTResponse({"error": {
653+
"handled": True,
654+
"message": str(e)
655+
}}, status=HTTP_INTERNAL_SERVER_ERROR)
625656

626657
return RESTResponse({"added": True})
627658

@@ -657,13 +688,19 @@ async def remove_tracker(self, request: Request) -> RESTResponse:
657688
parameters = await request.json()
658689
url = parameters.get("url")
659690
if not url:
660-
return RESTResponse({"error": "url parameter missing"}, status=HTTP_BAD_REQUEST)
691+
return RESTResponse({"error": {
692+
"handled": True,
693+
"message": "url parameter missing"
694+
}}, status=HTTP_BAD_REQUEST)
661695

662696
try:
663697
download.handle.replace_trackers([tracker for tracker in download.handle.trackers()
664698
if tracker["url"] != url])
665699
except RuntimeError as e:
666-
return RESTResponse({"error": str(e)}, status=HTTP_INTERNAL_SERVER_ERROR)
700+
return RESTResponse({"error": {
701+
"handled": True,
702+
"message": str(e)
703+
}}, status=HTTP_INTERNAL_SERVER_ERROR)
667704

668705
return RESTResponse({"removed": True})
669706

@@ -699,15 +736,21 @@ async def tracker_force_announce(self, request: Request) -> RESTResponse:
699736
parameters = await request.json()
700737
url = parameters.get("url")
701738
if not url:
702-
return RESTResponse({"error": "url parameter missing"}, status=HTTP_BAD_REQUEST)
739+
return RESTResponse({"error": {
740+
"handled": True,
741+
"message": "url parameter missing"
742+
}}, status=HTTP_BAD_REQUEST)
703743

704744
try:
705745
for i, tracker in enumerate(download.handle.trackers()):
706746
if tracker["url"] == url:
707747
download.handle.force_reannounce(0, i)
708748
break
709749
except RuntimeError as e:
710-
return RESTResponse({"error": str(e)}, status=HTTP_INTERNAL_SERVER_ERROR)
750+
return RESTResponse({"error": {
751+
"handled": True,
752+
"message": str(e)
753+
}}, status=HTTP_INTERNAL_SERVER_ERROR)
711754

712755
return RESTResponse({"forced": True})
713756

@@ -804,7 +847,10 @@ async def collapse_tree_directory(self, request: Request) -> RESTResponse:
804847
params = request.query
805848
path = params.get("path")
806849
if not path:
807-
return RESTResponse({"error": "path parameter missing"}, status=HTTP_BAD_REQUEST)
850+
return RESTResponse({"error": {
851+
"handled": True,
852+
"message": "path parameter missing"
853+
}}, status=HTTP_BAD_REQUEST)
808854

809855
download.tdef.torrent_file_tree.collapse(Path(path))
810856

@@ -845,7 +891,10 @@ async def expand_tree_directory(self, request: Request) -> RESTResponse:
845891
params = request.query
846892
path = params.get("path")
847893
if not path:
848-
return RESTResponse({"error": "path parameter missing"}, status=HTTP_BAD_REQUEST)
894+
return RESTResponse({"error": {
895+
"handled": True,
896+
"message": "path parameter missing"
897+
}}, status=HTTP_BAD_REQUEST)
849898

850899
download.tdef.torrent_file_tree.expand(Path(path))
851900

@@ -884,7 +933,10 @@ async def select_tree_path(self, request: Request) -> RESTResponse:
884933
params = request.query
885934
path = params.get("path")
886935
if not path:
887-
return RESTResponse({"error": "path parameter missing"}, status=HTTP_BAD_REQUEST)
936+
return RESTResponse({"error": {
937+
"handled": True,
938+
"message": "path parameter missing"
939+
}}, status=HTTP_BAD_REQUEST)
888940

889941
download.set_selected_file_or_dir(Path(path), True)
890942

@@ -923,7 +975,10 @@ async def deselect_tree_path(self, request: Request) -> RESTResponse:
923975
params = request.query
924976
path = params.get("path")
925977
if not path:
926-
return RESTResponse({"error": "path parameter missing"}, status=HTTP_BAD_REQUEST)
978+
return RESTResponse({"error": {
979+
"handled": True,
980+
"message": "path parameter missing"
981+
}}, status=HTTP_BAD_REQUEST)
927982

928983
download.set_selected_file_or_dir(Path(path), False)
929984

0 commit comments

Comments
 (0)