You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
10 years ago
|
from __future__ import absolute_import, division, print_function, with_statement
|
||
|
|
||
|
from hashlib import md5
|
||
|
|
||
|
from tornado.httpclient import HTTPRequest
|
||
|
from tornado.stack_context import ExceptionStackContext
|
||
|
from tornado.testing import AsyncHTTPTestCase
|
||
|
from tornado.test import httpclient_test
|
||
|
from tornado.test.util import unittest
|
||
|
from tornado.web import Application, RequestHandler
|
||
|
|
||
|
try:
|
||
|
import pycurl
|
||
|
except ImportError:
|
||
|
pycurl = None
|
||
|
|
||
|
if pycurl is not None:
|
||
|
from tornado.curl_httpclient import CurlAsyncHTTPClient
|
||
|
|
||
|
|
||
|
@unittest.skipIf(pycurl is None, "pycurl module not present")
|
||
|
class CurlHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):
|
||
|
def get_http_client(self):
|
||
|
client = CurlAsyncHTTPClient(io_loop=self.io_loop)
|
||
|
# make sure AsyncHTTPClient magic doesn't give us the wrong class
|
||
|
self.assertTrue(isinstance(client, CurlAsyncHTTPClient))
|
||
|
return client
|
||
|
|
||
|
|
||
|
class DigestAuthHandler(RequestHandler):
|
||
|
def get(self):
|
||
|
realm = 'test'
|
||
|
opaque = 'asdf'
|
||
|
# Real implementations would use a random nonce.
|
||
|
nonce = "1234"
|
||
|
username = 'foo'
|
||
|
password = 'bar'
|
||
|
|
||
|
auth_header = self.request.headers.get('Authorization', None)
|
||
|
if auth_header is not None:
|
||
|
auth_mode, params = auth_header.split(' ', 1)
|
||
|
assert auth_mode == 'Digest'
|
||
|
param_dict = {}
|
||
|
for pair in params.split(','):
|
||
|
k, v = pair.strip().split('=', 1)
|
||
|
if v[0] == '"' and v[-1] == '"':
|
||
|
v = v[1:-1]
|
||
|
param_dict[k] = v
|
||
|
assert param_dict['realm'] == realm
|
||
|
assert param_dict['opaque'] == opaque
|
||
|
assert param_dict['nonce'] == nonce
|
||
|
assert param_dict['username'] == username
|
||
|
assert param_dict['uri'] == self.request.path
|
||
|
h1 = md5('%s:%s:%s' % (username, realm, password)).hexdigest()
|
||
|
h2 = md5('%s:%s' % (self.request.method,
|
||
|
self.request.path)).hexdigest()
|
||
|
digest = md5('%s:%s:%s' % (h1, nonce, h2)).hexdigest()
|
||
|
if digest == param_dict['response']:
|
||
|
self.write('ok')
|
||
|
else:
|
||
|
self.write('fail')
|
||
|
else:
|
||
|
self.set_status(401)
|
||
|
self.set_header('WWW-Authenticate',
|
||
|
'Digest realm="%s", nonce="%s", opaque="%s"' %
|
||
|
(realm, nonce, opaque))
|
||
|
|
||
|
|
||
|
@unittest.skipIf(pycurl is None, "pycurl module not present")
|
||
|
class CurlHTTPClientTestCase(AsyncHTTPTestCase):
|
||
|
def setUp(self):
|
||
|
super(CurlHTTPClientTestCase, self).setUp()
|
||
|
self.http_client = CurlAsyncHTTPClient(self.io_loop)
|
||
|
|
||
|
def get_app(self):
|
||
|
return Application([
|
||
|
('/digest', DigestAuthHandler),
|
||
|
])
|
||
|
|
||
|
def test_prepare_curl_callback_stack_context(self):
|
||
|
exc_info = []
|
||
|
|
||
|
def error_handler(typ, value, tb):
|
||
|
exc_info.append((typ, value, tb))
|
||
|
self.stop()
|
||
|
return True
|
||
|
|
||
|
with ExceptionStackContext(error_handler):
|
||
|
request = HTTPRequest(self.get_url('/'),
|
||
|
prepare_curl_callback=lambda curl: 1 / 0)
|
||
|
self.http_client.fetch(request, callback=self.stop)
|
||
|
self.wait()
|
||
|
self.assertEqual(1, len(exc_info))
|
||
|
self.assertIs(exc_info[0][0], ZeroDivisionError)
|
||
|
|
||
|
def test_digest_auth(self):
|
||
|
response = self.fetch('/digest', auth_mode='digest',
|
||
|
auth_username='foo', auth_password='bar')
|
||
|
self.assertEqual(response.body, b'ok')
|