from tornado.testing import AsyncHTTPTestCase, LogTrapTestCase
from tornado.web import authenticated, Application, RequestHandler
+import os
+import pycurl
import re
import unittest
import urllib
+class HelloWorldRequestHandler(RequestHandler):
+ def get(self):
+ self.finish("Hello world")
+
class AuthRedirectRequestHandler(RequestHandler):
def initialize(self, login_url):
self.login_url = login_url
self.assertTrue(re.match(
'http://example.com/login\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute',
response.headers['Location']), response.headers['Location'])
+
+class SSLTest(AsyncHTTPTestCase, LogTrapTestCase):
+ def get_app(self):
+ return Application([('/', HelloWorldRequestHandler)])
+
+ def get_httpserver_options(self):
+ # Testing keys were generated with:
+ # openssl req -new -keyout tornado/test/test.key -out tornado/test/test.crt -nodes -days 3650 -x509
+ test_dir = os.path.dirname(__file__)
+ return dict(ssl_options=dict(
+ certfile=os.path.join(test_dir, 'test.crt'),
+ keyfile=os.path.join(test_dir, 'test.key')))
+
+ def test_ssl(self):
+ def disable_cert_check(curl):
+ # Our certificate was not signed by a CA, so don't check it
+ curl.setopt(pycurl.SSL_VERIFYPEER, 0)
+ self.http_client.fetch(self.get_url('/').replace('http', 'https'),
+ self.stop,
+ prepare_curl_callback=disable_cert_check)
+ response = self.wait()
+ self.assertEqual(response.body, "Hello world")
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIICSDCCAbGgAwIBAgIJAN1oTowzMbkzMA0GCSqGSIb3DQEBBQUAMD0xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRkwFwYDVQQKDBBUb3JuYWRvIFdl
+YiBUZXN0MB4XDTEwMDgyNTE4MjQ0NFoXDTIwMDgyMjE4MjQ0NFowPTELMAkGA1UE
+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExGTAXBgNVBAoMEFRvcm5hZG8gV2Vi
+IFRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALirW3mX4jbdFse2aZwW
+zszCJ1IsRDrzALpbvMYLLbIZqo+Z8v5aERKTRQpXFqGaZyY+tdwYy7X7YXcLtKqv
+jnw/MSeIaqkw5pROKz5aR0nkPLvcTmhJVLVPCLc8dFnIlu8aC9TrDhr90P+PzU39
+UG7zLweA9zXKBuW3Tjo5dMP3AgMBAAGjUDBOMB0GA1UdDgQWBBRhJjMBYrzddCFr
+/0vvPyHMeqgo0TAfBgNVHSMEGDAWgBRhJjMBYrzddCFr/0vvPyHMeqgo0TAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGP6GaxSfb21bikcqaK3ZKCC1sRJ
+tiCuvJZbBUFUCAzl05dYUfJZim/oWK+GqyUkUB8ciYivUNnn9OtS7DnlTgT2ws2e
+lNgn5cuFXoAGcHXzVlHG3yoywYBf3y0Dn20uzrlLXUWJAzoSLOt2LTaXvwlgm7hF
+W1q8SQ6UBshRw2X0
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALirW3mX4jbdFse2
+aZwWzszCJ1IsRDrzALpbvMYLLbIZqo+Z8v5aERKTRQpXFqGaZyY+tdwYy7X7YXcL
+tKqvjnw/MSeIaqkw5pROKz5aR0nkPLvcTmhJVLVPCLc8dFnIlu8aC9TrDhr90P+P
+zU39UG7zLweA9zXKBuW3Tjo5dMP3AgMBAAECgYEAiygNaWYrf95AcUQi9w00zpUr
+nj9fNvCwxr2kVbRMvd2balS/CC4EmXPCXdVcZ3B7dBVjYzSIJV0Fh/iZLtnVysD9
+fcNMZ+Cz71b/T0ItsNYOsJk0qUVyP52uqsqkNppIPJsD19C+ZeMLZj6iEiylZyl8
+2U16c/kVIjER63mUEGkCQQDayQOTGPJrKHqPAkUqzeJkfvHH2yCf+cySU+w6ezyr
+j9yxcq8aZoLusCebDVT+kz7RqnD5JePFvB38cMuepYBLAkEA2BTFdZx30f4moPNv
+JlXlPNJMUTUzsXG7n4vNc+18O5ous0NGQII8jZWrIcTrP8wiP9fF3JwUsKrJhcBn
+xRs3hQJBAIDUgz1YIE+HW3vgi1gkOh6RPdBAsVpiXtr/fggFz3j60qrO7FswaAMj
+SX8c/6KUlBYkNjgP3qruFf4zcUNvEzcCQQCaioCPFVE9ByBpjLG6IUTKsz2R9xL5
+nfYqrbpLZ1aq6iLsYvkjugHE4X57sHLwNfdo4dHJbnf9wqhO2MVe25BhAkBdKYpY
+7OKc/2mmMbJDhVBgoixz/muN/5VjdfbvVY48naZkJF1p1tmogqPC5F1jPCS4rM+S
+FfPJIHRNEn2oktw5
+-----END PRIVATE KEY-----
self.http_client = AsyncHTTPClient(io_loop=self.io_loop)
self._app = self.get_app()
- self.http_server = HTTPServer(self._app, io_loop=self.io_loop)
+ self.http_server = HTTPServer(self._app, io_loop=self.io_loop,
+ **self.get_httpserver_options())
self.http_server.listen(self.get_http_port())
def get_app(self):
"""
raise NotImplementedError()
+ def get_httpserver_options(self):
+ """May be overridden by subclasses to return additional
+ keyword arguments for HTTPServer.
+ """
+ return {}
+
def get_http_port(self):
"""Returns the port used by the HTTPServer.