diff --git a/tornado/curl_httpclient.py b/tornado/curl_httpclient.py index b8fd4052..53824c84 100644 --- a/tornado/curl_httpclient.py +++ b/tornado/curl_httpclient.py @@ -271,7 +271,7 @@ def _curl_create(max_simultaneous_connections=None): def _curl_setup_request(curl, request, buffer, headers): - curl.setopt(pycurl.URL, request.url) + curl.setopt(pycurl.URL, utf8(request.url)) # libcurl's magic "Expect: 100-continue" behavior causes delays # with servers that don't support it (which include, among others, diff --git a/tornado/httpclient.py b/tornado/httpclient.py index a6ad4fa1..1280a47d 100644 --- a/tornado/httpclient.py +++ b/tornado/httpclient.py @@ -54,9 +54,11 @@ class HTTPClient(object): except httpclient.HTTPError, e: print "Error:", e """ - def __init__(self): + def __init__(self, async_client_class=None): self._io_loop = IOLoop() - self._async_client = AsyncHTTPClient(self._io_loop) + if async_client_class is None: + async_client_class = AsyncHTTPClient + self._async_client = async_client_class(self._io_loop) self._response = None self._closed = False diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 03634852..5eb46208 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -118,7 +118,8 @@ class HTTPConnectionTest(AsyncHTTPTestCase, LogTrapTestCase): return Application(self.get_handlers()) def raw_fetch(self, headers, body): - conn = RawRequestHTTPConnection(self.io_loop, self.http_client, + client = SimpleAsyncHTTPClient(self.io_loop) + conn = RawRequestHTTPConnection(self.io_loop, client, httpclient.HTTPRequest(self.get_url("/")), None, self.stop, 1024*1024) @@ -127,6 +128,7 @@ class HTTPConnectionTest(AsyncHTTPTestCase, LogTrapTestCase): [utf8("Content-Length: %d\r\n" % len(body))]) + b("\r\n") + body) response = self.wait() + client.close() response.rethrow() return response diff --git a/tornado/test/process_test.py b/tornado/test/process_test.py index 91f75b0a..de9ae523 100644 --- a/tornado/test/process_test.py +++ b/tornado/test/process_test.py @@ -9,6 +9,7 @@ from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.netutil import bind_sockets from tornado.process import fork_processes, task_id +from tornado.simple_httpclient import SimpleAsyncHTTPClient from tornado.testing import LogTrapTestCase, get_unused_port from tornado.web import RequestHandler, Application @@ -72,7 +73,11 @@ class ProcessTest(LogTrapTestCase): signal.alarm(5) self.assertEqual(id, task_id()) for sock in sockets: sock.close() - client = HTTPClient() + # Always use SimpleAsyncHTTPClient here; the curl + # version appears to get confused sometimes if the + # connection gets closed before it's had a chance to + # switch from writing mode to reading mode. + client = HTTPClient(SimpleAsyncHTTPClient) def fetch(url, fail_ok=False): try: diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index 7b7eb19e..a65c8c68 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -55,6 +55,10 @@ class NoContentHandler(RequestHandler): self.set_status(204) class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): + def setUp(self): + super(SimpleHTTPClientTestCase, self).setUp() + self.http_client = SimpleAsyncHTTPClient(self.io_loop) + def get_app(self): # callable objects to finish pending /trigger requests self.triggers = collections.deque() diff --git a/tox.ini b/tox.ini index 96e24276..30a78088 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ [tox] # "-full" variants include optional dependencies, to ensure # that things work both in a bare install and with all the extras. -envlist = py27-full, py25-full, py32, pypy, py25, py26, py26-full, py27 +envlist = py27-full, py27-curl, py25-full, py32, pypy, py25, py26, py26-full, py27 [testenv] commands = python -m tornado.test.runtests {posargs:} @@ -52,6 +52,17 @@ deps = pycurl twisted==11.0.0 +[testenv:py27-curl] +# Same as py27-full, but runs the tests with curl_httpclient by default. +# Note that httpclient_test is always run with both client implementations; +# this flag controls which client all the other tests use. +basepython = python2.7 +deps = + MySQL-python + pycurl + twisted==11.0.0 +commands = python -m tornado.test.runtests --httpclient=tornado.curl_httpclient.CurlAsyncHTTPClient {posargs:} + # No pypy-full yet: pycurl doesn't build with pypy, and installing # twisted under pypy takes a *very* long time. MySQL-python builds with # pypy, but doesn't work.