66import random
77import re
88import string
9- from urllib .parse import urlparse
9+ from urllib .parse import urlparse , quote
1010import uuid
1111import os
1212
@@ -161,11 +161,12 @@ async def launch(self, image, username, server_name='', repo_url='', extra_args=
161161 """
162162 # TODO: validate the image argument?
163163
164+ escaped_username = quote (username , safe = '@~' )
164165 if self .create_user :
165166 # create a new user
166167 app_log .info ("Creating user %s for image %s" , username , image )
167168 try :
168- await self .api_request ('users/%s' % username , body = b'' , method = 'POST' )
169+ await self .api_request ('users/%s' % escaped_username , body = b'' , method = 'POST' )
169170 except HTTPError as e :
170171 if e .response :
171172 body = e .response .body
@@ -178,13 +179,13 @@ async def launch(self, image, username, server_name='', repo_url='', extra_args=
178179 elif server_name == '' :
179180 # authentication is enabled but not named servers
180181 # check if user has a running server ('')
181- user_data = await self .get_user_data (username )
182+ user_data = await self .get_user_data (escaped_username )
182183 if server_name in user_data ['servers' ]:
183184 raise web .HTTPError (409 , "User %s already has a running server." % username )
184185 elif self .named_server_limit_per_user > 0 :
185186 # authentication is enabled with named servers
186187 # check if user has already reached to the limit of named servers
187- user_data = await self .get_user_data (username )
188+ user_data = await self .get_user_data (escaped_username )
188189 len_named_spawners = len ([s for s in user_data ['servers' ] if s != '' ])
189190 if self .named_server_limit_per_user <= len_named_spawners :
190191 raise web .HTTPError (
@@ -213,7 +214,7 @@ async def launch(self, image, username, server_name='', repo_url='', extra_args=
213214 app_log .info ("Starting server%s for user %s with image %s" , _server_name , username , image )
214215 try :
215216 resp = await self .api_request (
216- 'users/{}/servers/{}' .format (username , server_name ),
217+ 'users/{}/servers/{}' .format (escaped_username , server_name ),
217218 method = 'POST' ,
218219 body = json .dumps (data ).encode ('utf8' ),
219220 )
@@ -222,7 +223,7 @@ async def launch(self, image, username, server_name='', repo_url='', extra_args=
222223 # We wait for it!
223224 # NOTE: This ends up being about ten minutes
224225 for i in range (64 ):
225- user_data = await self .get_user_data (username )
226+ user_data = await self .get_user_data (escaped_username )
226227 if user_data ['servers' ][server_name ]['ready' ]:
227228 break
228229 if not user_data ['servers' ][server_name ]['pending' ]:
@@ -244,5 +245,5 @@ async def launch(self, image, username, server_name='', repo_url='', extra_args=
244245 format (_server_name , username , e , body ))
245246 raise web .HTTPError (500 , "Failed to launch image %s" % image )
246247
247- data ['url' ] = self .hub_url + 'user/%s/%s' % (username , server_name )
248+ data ['url' ] = self .hub_url + 'user/%s/%s' % (escaped_username , server_name )
248249 return data
0 commit comments