1+ import base64
12import os
23import email
34import urllib .parse
@@ -197,6 +198,50 @@ def handle_request(self, request_handler):
197198 return self ._return_auth_challenge (request_handler )
198199 return True
199200
201+
202+ class BasicAuthHandler (http .server .BaseHTTPRequestHandler ):
203+ """Handler for performing basic authentication."""
204+ # Server side values
205+ USER = 'testUser'
206+ PASSWD = 'testPass'
207+ REALM = 'Test'
208+ USER_PASSWD = "%s:%s" % (USER , PASSWD )
209+ ENCODED_AUTH = base64 .b64encode (USER_PASSWD .encode ('ascii' )).decode ('ascii' )
210+
211+ def __init__ (self , * args , ** kwargs ):
212+ http .server .BaseHTTPRequestHandler .__init__ (self , * args , ** kwargs )
213+
214+ def log_message (self , format , * args ):
215+ # Suppress console log message
216+ pass
217+
218+ def do_HEAD (self ):
219+ self .send_response (200 )
220+ self .send_header ("Content-type" , "text/html" )
221+ self .end_headers ()
222+
223+ def do_AUTHHEAD (self ):
224+ self .send_response (401 )
225+ self .send_header ("WWW-Authenticate" , "Basic realm=\" %s\" " % self .REALM )
226+ self .send_header ("Content-type" , "text/html" )
227+ self .end_headers ()
228+
229+ def do_GET (self ):
230+ if not self .headers .get ("Authorization" , "" ):
231+ self .do_AUTHHEAD ()
232+ self .wfile .write (b"No Auth header received" )
233+ elif self .headers .get (
234+ "Authorization" , "" ) == "Basic " + self .ENCODED_AUTH :
235+ self .send_response (200 )
236+ self .end_headers ()
237+ self .wfile .write (b"It works" )
238+ else :
239+ # Request Unauthorized
240+ self .do_AUTHHEAD ()
241+ self .wfile .close ()
242+
243+
244+
200245# Proxy test infrastructure
201246
202247class FakeProxyHandler (http .server .BaseHTTPRequestHandler ):
@@ -232,6 +277,43 @@ def do_GET(self):
232277
233278# Test cases
234279
280+ @unittest .skipUnless (threading , "Threading required for this test." )
281+ class BasicAuthTests (unittest .TestCase ):
282+ USER = "testUser"
283+ PASSWD = "testPass"
284+ INCORRECT_PASSWD = "Incorrect"
285+ REALM = "Test"
286+
287+ def setUp (self ):
288+ super (BasicAuthTests , self ).setUp ()
289+ # With Basic Authentication
290+ def http_server_with_basic_auth_handler (* args , ** kwargs ):
291+ return BasicAuthHandler (* args , ** kwargs )
292+ self .server = LoopbackHttpServerThread (http_server_with_basic_auth_handler )
293+ self .server_url = 'http://127.0.0.1:%s' % self .server .port
294+ self .server .start ()
295+ self .server .ready .wait ()
296+
297+ def tearDown (self ):
298+ self .server .stop ()
299+ super (BasicAuthTests , self ).tearDown ()
300+
301+ def test_basic_auth_success (self ):
302+ ah = urllib .request .HTTPBasicAuthHandler ()
303+ ah .add_password (self .REALM , self .server_url , self .USER , self .PASSWD )
304+ urllib .request .install_opener (urllib .request .build_opener (ah ))
305+ try :
306+ self .assertTrue (urllib .request .urlopen (self .server_url ))
307+ except urllib .error .HTTPError :
308+ self .fail ("Basic auth failed for the url: %s" , self .server_url )
309+
310+ def test_basic_auth_httperror (self ):
311+ ah = urllib .request .HTTPBasicAuthHandler ()
312+ ah .add_password (self .REALM , self .server_url , self .USER , self .INCORRECT_PASSWD )
313+ urllib .request .install_opener (urllib .request .build_opener (ah ))
314+ self .assertRaises (urllib .error .HTTPError , urllib .request .urlopen , self .server_url )
315+
316+
235317@unittest .skipUnless (threading , "Threading required for this test." )
236318class ProxyAuthTests (unittest .TestCase ):
237319 URL = "http://localhost"
@@ -245,6 +327,7 @@ def setUp(self):
245327 self .digest_auth_handler = DigestAuthHandler ()
246328 self .digest_auth_handler .set_users ({self .USER : self .PASSWD })
247329 self .digest_auth_handler .set_realm (self .REALM )
330+ # With Digest Authentication.
248331 def create_fake_proxy_handler (* args , ** kwargs ):
249332 return FakeProxyHandler (self .digest_auth_handler , * args , ** kwargs )
250333
0 commit comments