1515from .. import __version__ , orm
1616from ..metrics import SERVER_POLL_DURATION_SECONDS , ServerPollStatus
1717from ..scopes import describe_raw_scopes , needs_scope
18- from ..utils import maybe_future , url_escape_path , url_path_join , utcnow
18+ from ..utils import (
19+ format_exception ,
20+ maybe_future ,
21+ url_escape_path ,
22+ url_path_join ,
23+ utcnow ,
24+ )
1925from .base import BaseHandler
2026
2127
@@ -92,14 +98,17 @@ class SpawnHandler(BaseHandler):
9298
9399 default_url = None
94100
95- async def _render_form (self , for_user , spawner_options_form , message = '' ):
101+ async def _render_form (
102+ self , for_user , spawner_options_form , message = '' , html_message = ''
103+ ):
96104 auth_state = await for_user .get_auth_state ()
97105 return await self .render_template (
98106 'spawn.html' ,
99107 for_user = for_user ,
100108 auth_state = auth_state ,
101109 spawner_options_form = spawner_options_form ,
102110 error_message = message ,
111+ html_error_message = html_message ,
103112 url = url_concat (
104113 self .request .uri , {"_xsrf" : self .xsrf_token .decode ('ascii' )}
105114 ),
@@ -177,14 +186,15 @@ async def _get(self, user_name, server_name):
177186 await spawner .run_auth_state_hook (auth_state )
178187
179188 # Try to start server directly when query arguments are passed.
180- error_message = ''
181189 query_options = {}
182190 for key , byte_list in self .request .query_arguments .items ():
183191 query_options [key ] = [bs .decode ('utf8' ) for bs in byte_list ]
184192
185193 # 'next' is reserved argument for redirect after spawn
186194 query_options .pop ('next' , None )
187195
196+ spawn_exc = None
197+
188198 if len (query_options ) > 0 :
189199 try :
190200 self .log .debug (
@@ -200,16 +210,31 @@ async def _get(self, user_name, server_name):
200210 "Failed to spawn single-user server with query arguments" ,
201211 exc_info = True ,
202212 )
203- error_message = str ( e )
213+ spawn_exc = e
204214 # fallback to behavior without failing query arguments
205215
206216 spawner_options_form = await spawner .get_options_form ()
207217 if spawner_options_form :
208218 self .log .debug ("Serving options form for %s" , spawner ._log_name )
219+
220+ # Explicitly catch HTTPError and report them to the client
221+ # This may need scoping to particular error codes.
222+ if isinstance (spawn_exc , web .HTTPError ):
223+ self .set_status (spawn_exc .status_code )
224+
225+ for name , value in spawn_exc .headers .items ():
226+ self .set_header (name , value )
227+
228+ if spawn_exc :
229+ error_message , error_html_message = format_exception (spawn_exc )
230+ else :
231+ error_message = error_html_message = None
232+
209233 form = await self ._render_form (
210234 for_user = user ,
211235 spawner_options_form = spawner_options_form ,
212236 message = error_message ,
237+ html_message = error_html_message ,
213238 )
214239 self .finish (form )
215240 else :
@@ -265,9 +290,23 @@ async def _post(self, user_name, server_name):
265290 self .log .error (
266291 "Failed to spawn single-user server with form" , exc_info = True
267292 )
293+
294+ # Explicitly catch HTTPError and report them to the client
295+ # This may need scoping to particular error codes.
296+ if isinstance (e , web .HTTPError ):
297+ self .set_status (e .status_code )
298+
299+ for name , value in e .headers .items ():
300+ self .set_header (name , value )
301+
302+ error_message , error_html_message = format_exception (e )
303+
268304 spawner_options_form = await user .spawner .get_options_form ()
269305 form = await self ._render_form (
270- for_user = user , spawner_options_form = spawner_options_form , message = str (e )
306+ for_user = user ,
307+ spawner_options_form = spawner_options_form ,
308+ message = error_message ,
309+ html_message = error_html_message ,
271310 )
272311 self .finish (form )
273312 return
@@ -379,15 +418,17 @@ async def get(self, user_name, server_name=''):
379418 if isinstance (exc , web .HTTPError ):
380419 status_code = exc .status_code
381420 self .set_status (status_code )
421+
422+ message , html_message = format_exception (exc , only_jupyterhub = True )
382423 html = await self .render_template (
383424 "not_running.html" ,
384425 user = user ,
385426 auth_state = auth_state ,
386427 server_name = server_name ,
387428 spawn_url = spawn_url ,
388429 failed = True ,
389- failed_html_message = getattr ( exc , 'jupyterhub_html_message' , '' ) ,
390- failed_message = getattr ( exc , 'jupyterhub_message' , '' ) ,
430+ failed_html_message = html_message ,
431+ failed_message = message ,
391432 exception = exc ,
392433 )
393434 self .finish (html )
0 commit comments