@@ -13,11 +13,41 @@ class RouteHandler(APIHandler):
1313 # Jupyter server
1414 @tornado .web .authenticated
1515 async def get (self ):
16- path = self .get_query_argument ("path" )
17- # Use Jupyter Server’s contents_manager, not direct filesystem access.
18- model = await ensure_async (
19- self .contents_manager .get (path , type = "file" , format = "text" , content = True )
20- )
16+ path = self .get_query_argument ("path" , default = None )
17+ if not path :
18+ self .set_status (400 )
19+ self .set_header ("Content-Type" , "application/json" )
20+ self .finish (
21+ json .dumps (
22+ {
23+ "code" : 400 ,
24+ "message" : "Missing required 'path' parameter" ,
25+ }
26+ )
27+ )
28+ return
29+ try :
30+ model = await ensure_async (
31+ self .contents_manager .get (
32+ path , type = "file" , format = "text" , content = True
33+ )
34+ )
35+ except FileNotFoundError as e :
36+ self .set_status (404 )
37+ self .set_header ("Content-Type" , "application/json" )
38+ self .finish (json .dumps ({"code" : 404 , "message" : "File not found" }))
39+ return
40+ except PermissionError as e :
41+ self .set_status (403 )
42+ self .set_header ("Content-Type" , "application/json" )
43+ self .finish (json .dumps ({"code" : 403 , "message" : "Permission denied" }))
44+ return
45+ except Exception as e :
46+ self .log .exception ("Error retrieving file" )
47+ self .set_status (500 )
48+ self .set_header ("Content-Type" , "application/json" )
49+ self .finish (json .dumps ({"code" : 500 , "message" : "Internal server error" }))
50+ return
2151 # Convert datetimes to strings so JSON can handle them
2252 for key in ("created" , "last_modified" ):
2353 if isinstance (model .get (key ), datetime ):
0 commit comments