88import socket
99from asyncio import Lock
1010from copy import copy
11+ from html import escape
1112from tempfile import mkdtemp
1213from urllib .parse import quote , urlparse , urlunparse
1314
1617from jupyter_server .utils import ensure_async , url_path_join
1718from simpervisor import SupervisedProcess
1819from tornado import httpclient , httputil , web
19- from tornado .escape import xhtml_escape
2020from tornado .simple_httpclient import SimpleAsyncHTTPClient
2121from traitlets import Bytes , Dict , Instance , Integer , Unicode , Union , default , observe
2222from traitlets .traitlets import HasTraits
@@ -328,7 +328,7 @@ async def proxy(self, host, port, proxied_path):
328328 self .write (
329329 "Host '{host}' is not allowed. "
330330 "See https://jupyter-server-proxy.readthedocs.io/en/latest/arbitrary-ports-hosts.html for info." .format (
331- host = xhtml_escape (host )
331+ host = escape (host )
332332 )
333333 )
334334 return
@@ -393,7 +393,7 @@ async def proxy(self, host, port, proxied_path):
393393 if err .code == 599 :
394394 self ._record_activity ()
395395 self .set_status (599 )
396- self .write (str (err ))
396+ self .write (escape ( str (err ) ))
397397 return
398398 else :
399399 raise
@@ -404,7 +404,7 @@ async def proxy(self, host, port, proxied_path):
404404 # For all non http errors...
405405 if response .error and type (response .error ) is not httpclient .HTTPError :
406406 self .set_status (500 )
407- self .write (str (response .error ))
407+ self .write (escape ( str (response .error ) ))
408408 else :
409409 # Represent the original response as a RewritableResponse object.
410410 original_response = RewritableResponse (orig_response = response )
0 commit comments