Skip to content

Commit 2ffee9e

Browse files
authored
Merge pull request #19 from scivisum/http_auth
Http auth
2 parents f9ed1cb + 6c4c342 commit 2ffee9e

File tree

4 files changed

+84
-3
lines changed

4 files changed

+84
-3
lines changed

browserdebuggertools/chrome/interface.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import contextlib
22
import time
33
import logging
4-
from base64 import b64decode
4+
from base64 import b64decode, b64encode
55

66
from browserdebuggertools.sockethandler import SocketHandler
77
from browserdebuggertools.exceptions import (
@@ -215,3 +215,18 @@ def emulate_network_conditions(self, latency, download, upload, offline=False):
215215
}
216216

217217
return self.execute("Network", "emulateNetworkConditions", network_conditions)
218+
219+
def set_basic_auth(self, username, password):
220+
"""
221+
Creates a basic type Authorization header from the username and password strings
222+
and applies it to all requests
223+
"""
224+
auth = "Basic " + b64encode("%s:%s" % (username, password))
225+
self.set_request_headers({"Authorization": auth})
226+
227+
def set_request_headers(self, headers):
228+
"""
229+
The specified headers are applied to all requests
230+
:param headers: A dictionary of the form {"headerKey": "headerValue"}
231+
"""
232+
self.execute("Network", "setExtraHTTPHeaders", {"headers": headers})

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
setup(
1313
name="browserdebuggertools",
14-
version="3.1.0",
14+
version="3.2.0",
1515
packages=PACKAGES,
1616
install_requires=requires,
1717
license="GNU General Public License v3",

tests/e2etests/chrome/test_interface.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def test_took_expected_time(self):
223223
start = time.time()
224224
self.assertTrue(self.waitForEventWithMethod("Network.loadingFinished"))
225225
time_taken = time.time() - start
226-
self.assertEqual(10, int(round(time_taken)))
226+
self.assertIn(int(round(time_taken)), [10, 11]) # Headed browser is a bit slower
227227

228228

229229
class Test_ChromeInterface_emulate_network_conditions_headed(
@@ -236,3 +236,34 @@ class Test_ChromeInterface_emulate_network_conditions_headless(
236236
HeadlessChromeInterfaceTest, ChromeInterface_emulate_network_conditions, TestCase
237237
):
238238
pass
239+
240+
241+
class ChromeInterface_set_basic_auth(object):
242+
243+
def test_standard_auth_page(self):
244+
245+
self.devtools_client.enable_domain("Network")
246+
url = "http://username:password@localhost:%s/auth_challenge" % self.testSite.port
247+
self.devtools_client.navigate(url=url)
248+
self._assert_dom_complete()
249+
250+
responses_received = []
251+
for event in self.devtools_client.get_events("Network"):
252+
if event.get("method") == "Network.responseReceived":
253+
responses_received.append(event["params"]["response"]["status"])
254+
255+
self.assertTrue(len(responses_received) >= 2) # Headed browser creates extra requests
256+
self.assertIn(200, responses_received)
257+
self.assertNotIn(401, responses_received) # Devtools genuinely doesn't report these
258+
259+
260+
class Test_ChromeInterface_set_baic_auth_headed(
261+
HeadedChromeInterfaceTest, ChromeInterface_set_basic_auth, TestCase
262+
):
263+
pass
264+
265+
266+
class Test_ChromeInterface_set_baic_auth_headless(
267+
HeadlessChromeInterfaceTest, ChromeInterface_set_basic_auth, TestCase
268+
):
269+
pass

tests/e2etests/testsite/start.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import multiprocessing
22
import time
3+
from base64 import b64decode
34

45
import cherrypy
56

@@ -35,6 +36,40 @@ def javascript_file(self, response_time=None):
3536
def big_body(self, size=1000000):
3637
return "T" * size
3738

39+
@cherrypy.expose
40+
def auth_challenge(self, authorized_username="username", authorized_password="password",
41+
response_body=None):
42+
43+
if self.is_authenticated(authorized_username, authorized_password):
44+
45+
if response_body:
46+
return response_body
47+
48+
return """
49+
<html>
50+
<head><script src="/auth_challenge?response_body=null"></script></head>
51+
<body>
52+
Authorized
53+
</body>
54+
</html>
55+
"""
56+
cherrypy.response.headers["WWW-Authenticate"] = "basic"
57+
cherrypy.response.status = 401
58+
return "Need to authorize"
59+
60+
@staticmethod
61+
def is_authenticated(authorized_username, authorized_password):
62+
63+
if "Authorization" in cherrypy.request.headers:
64+
65+
auth_string = str(cherrypy.request.headers["Authorization"])
66+
secret = auth_string.split("Basic ")[1]
67+
credentials = b64decode(secret).decode()
68+
this_username, this_password = tuple(credentials.split(":"))
69+
if (this_username == authorized_username) and (this_password == authorized_password):
70+
return True
71+
return False
72+
3873

3974
class Server(object):
4075

0 commit comments

Comments
 (0)