Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | #!/usr/bin/env python |
michael@0 | 2 | |
michael@0 | 3 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 5 | # You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 6 | |
michael@0 | 7 | import mozhttpd |
michael@0 | 8 | import urllib2 |
michael@0 | 9 | import os |
michael@0 | 10 | import unittest |
michael@0 | 11 | import re |
michael@0 | 12 | import json |
michael@0 | 13 | import tempfile |
michael@0 | 14 | |
michael@0 | 15 | here = os.path.dirname(os.path.abspath(__file__)) |
michael@0 | 16 | |
michael@0 | 17 | class ApiTest(unittest.TestCase): |
michael@0 | 18 | resource_get_called = 0 |
michael@0 | 19 | resource_post_called = 0 |
michael@0 | 20 | resource_del_called = 0 |
michael@0 | 21 | |
michael@0 | 22 | @mozhttpd.handlers.json_response |
michael@0 | 23 | def resource_get(self, request, objid): |
michael@0 | 24 | self.resource_get_called += 1 |
michael@0 | 25 | return (200, { 'called': self.resource_get_called, |
michael@0 | 26 | 'id': objid, |
michael@0 | 27 | 'query': request.query }) |
michael@0 | 28 | |
michael@0 | 29 | @mozhttpd.handlers.json_response |
michael@0 | 30 | def resource_post(self, request): |
michael@0 | 31 | self.resource_post_called += 1 |
michael@0 | 32 | return (201, { 'called': self.resource_post_called, |
michael@0 | 33 | 'data': json.loads(request.body), |
michael@0 | 34 | 'query': request.query }) |
michael@0 | 35 | |
michael@0 | 36 | @mozhttpd.handlers.json_response |
michael@0 | 37 | def resource_del(self, request, objid): |
michael@0 | 38 | self.resource_del_called += 1 |
michael@0 | 39 | return (200, { 'called': self.resource_del_called, |
michael@0 | 40 | 'id': objid, |
michael@0 | 41 | 'query': request.query }) |
michael@0 | 42 | |
michael@0 | 43 | def get_url(self, path, server_port, querystr): |
michael@0 | 44 | url = "http://127.0.0.1:%s%s" % (server_port, path) |
michael@0 | 45 | if querystr: |
michael@0 | 46 | url += "?%s" % querystr |
michael@0 | 47 | return url |
michael@0 | 48 | |
michael@0 | 49 | def try_get(self, server_port, querystr): |
michael@0 | 50 | self.resource_get_called = 0 |
michael@0 | 51 | |
michael@0 | 52 | f = urllib2.urlopen(self.get_url('/api/resource/1', server_port, querystr)) |
michael@0 | 53 | try: |
michael@0 | 54 | self.assertEqual(f.getcode(), 200) |
michael@0 | 55 | except AttributeError: |
michael@0 | 56 | pass # python 2.4 |
michael@0 | 57 | self.assertEqual(json.loads(f.read()), { 'called': 1, 'id': str(1), 'query': querystr }) |
michael@0 | 58 | self.assertEqual(self.resource_get_called, 1) |
michael@0 | 59 | |
michael@0 | 60 | def try_post(self, server_port, querystr): |
michael@0 | 61 | self.resource_post_called = 0 |
michael@0 | 62 | |
michael@0 | 63 | postdata = { 'hamburgers': '1234' } |
michael@0 | 64 | try: |
michael@0 | 65 | f = urllib2.urlopen(self.get_url('/api/resource/', server_port, querystr), |
michael@0 | 66 | data=json.dumps(postdata)) |
michael@0 | 67 | except urllib2.HTTPError, e: |
michael@0 | 68 | # python 2.4 |
michael@0 | 69 | self.assertEqual(e.code, 201) |
michael@0 | 70 | body = e.fp.read() |
michael@0 | 71 | else: |
michael@0 | 72 | self.assertEqual(f.getcode(), 201) |
michael@0 | 73 | body = f.read() |
michael@0 | 74 | self.assertEqual(json.loads(body), { 'called': 1, |
michael@0 | 75 | 'data': postdata, |
michael@0 | 76 | 'query': querystr }) |
michael@0 | 77 | self.assertEqual(self.resource_post_called, 1) |
michael@0 | 78 | |
michael@0 | 79 | def try_del(self, server_port, querystr): |
michael@0 | 80 | self.resource_del_called = 0 |
michael@0 | 81 | |
michael@0 | 82 | opener = urllib2.build_opener(urllib2.HTTPHandler) |
michael@0 | 83 | request = urllib2.Request(self.get_url('/api/resource/1', server_port, querystr)) |
michael@0 | 84 | request.get_method = lambda: 'DEL' |
michael@0 | 85 | f = opener.open(request) |
michael@0 | 86 | |
michael@0 | 87 | try: |
michael@0 | 88 | self.assertEqual(f.getcode(), 200) |
michael@0 | 89 | except AttributeError: |
michael@0 | 90 | pass # python 2.4 |
michael@0 | 91 | self.assertEqual(json.loads(f.read()), { 'called': 1, 'id': str(1), 'query': querystr }) |
michael@0 | 92 | self.assertEqual(self.resource_del_called, 1) |
michael@0 | 93 | |
michael@0 | 94 | def test_api(self): |
michael@0 | 95 | httpd = mozhttpd.MozHttpd(port=0, |
michael@0 | 96 | urlhandlers = [ { 'method': 'GET', |
michael@0 | 97 | 'path': '/api/resource/([^/]+)/?', |
michael@0 | 98 | 'function': self.resource_get }, |
michael@0 | 99 | { 'method': 'POST', |
michael@0 | 100 | 'path': '/api/resource/?', |
michael@0 | 101 | 'function': self.resource_post }, |
michael@0 | 102 | { 'method': 'DEL', |
michael@0 | 103 | 'path': '/api/resource/([^/]+)/?', |
michael@0 | 104 | 'function': self.resource_del } |
michael@0 | 105 | ]) |
michael@0 | 106 | httpd.start(block=False) |
michael@0 | 107 | |
michael@0 | 108 | server_port = httpd.httpd.server_port |
michael@0 | 109 | |
michael@0 | 110 | # GET |
michael@0 | 111 | self.try_get(server_port, '') |
michael@0 | 112 | self.try_get(server_port, '?foo=bar') |
michael@0 | 113 | |
michael@0 | 114 | # POST |
michael@0 | 115 | self.try_post(server_port, '') |
michael@0 | 116 | self.try_post(server_port, '?foo=bar') |
michael@0 | 117 | |
michael@0 | 118 | # DEL |
michael@0 | 119 | self.try_del(server_port, '') |
michael@0 | 120 | self.try_del(server_port, '?foo=bar') |
michael@0 | 121 | |
michael@0 | 122 | # GET: By default we don't serve any files if we just define an API |
michael@0 | 123 | f = None |
michael@0 | 124 | exception_thrown = False |
michael@0 | 125 | try: |
michael@0 | 126 | f = urllib2.urlopen(self.get_url('/', server_port, None)) |
michael@0 | 127 | except urllib2.HTTPError, e: |
michael@0 | 128 | self.assertEqual(e.code, 404) |
michael@0 | 129 | exception_thrown = True |
michael@0 | 130 | self.assertTrue(exception_thrown) |
michael@0 | 131 | |
michael@0 | 132 | def test_nonexistent_resources(self): |
michael@0 | 133 | # Create a server with a placeholder handler so we don't fall back |
michael@0 | 134 | # to serving local files |
michael@0 | 135 | httpd = mozhttpd.MozHttpd(port=0) |
michael@0 | 136 | httpd.start(block=False) |
michael@0 | 137 | server_port = httpd.httpd.server_port |
michael@0 | 138 | |
michael@0 | 139 | # GET: Return 404 for non-existent endpoint |
michael@0 | 140 | f = None |
michael@0 | 141 | exception_thrown = False |
michael@0 | 142 | try: |
michael@0 | 143 | f = urllib2.urlopen(self.get_url('/api/resource/', server_port, None)) |
michael@0 | 144 | except urllib2.HTTPError, e: |
michael@0 | 145 | self.assertEqual(e.code, 404) |
michael@0 | 146 | exception_thrown = True |
michael@0 | 147 | self.assertTrue(exception_thrown) |
michael@0 | 148 | |
michael@0 | 149 | # POST: POST should also return 404 |
michael@0 | 150 | f = None |
michael@0 | 151 | exception_thrown = False |
michael@0 | 152 | try: |
michael@0 | 153 | f = urllib2.urlopen(self.get_url('/api/resource/', server_port, None), |
michael@0 | 154 | data=json.dumps({})) |
michael@0 | 155 | except urllib2.HTTPError, e: |
michael@0 | 156 | self.assertEqual(e.code, 404) |
michael@0 | 157 | exception_thrown = True |
michael@0 | 158 | self.assertTrue(exception_thrown) |
michael@0 | 159 | |
michael@0 | 160 | # DEL: DEL should also return 404 |
michael@0 | 161 | f = None |
michael@0 | 162 | exception_thrown = False |
michael@0 | 163 | try: |
michael@0 | 164 | opener = urllib2.build_opener(urllib2.HTTPHandler) |
michael@0 | 165 | request = urllib2.Request(self.get_url('/api/resource/', server_port, |
michael@0 | 166 | None)) |
michael@0 | 167 | request.get_method = lambda: 'DEL' |
michael@0 | 168 | f = opener.open(request) |
michael@0 | 169 | except urllib2.HTTPError, e: |
michael@0 | 170 | self.assertEqual(e.code, 404) |
michael@0 | 171 | exception_thrown = True |
michael@0 | 172 | self.assertTrue(exception_thrown) |
michael@0 | 173 | |
michael@0 | 174 | def test_api_with_docroot(self): |
michael@0 | 175 | httpd = mozhttpd.MozHttpd(port=0, docroot=here, |
michael@0 | 176 | urlhandlers = [ { 'method': 'GET', |
michael@0 | 177 | 'path': '/api/resource/([^/]+)/?', |
michael@0 | 178 | 'function': self.resource_get } ]) |
michael@0 | 179 | httpd.start(block=False) |
michael@0 | 180 | server_port = httpd.httpd.server_port |
michael@0 | 181 | |
michael@0 | 182 | # We defined a docroot, so we expect a directory listing |
michael@0 | 183 | f = urllib2.urlopen(self.get_url('/', server_port, None)) |
michael@0 | 184 | try: |
michael@0 | 185 | self.assertEqual(f.getcode(), 200) |
michael@0 | 186 | except AttributeError: |
michael@0 | 187 | pass # python 2.4 |
michael@0 | 188 | self.assertTrue('Directory listing for' in f.read()) |
michael@0 | 189 | |
michael@0 | 190 | # Make sure API methods still work |
michael@0 | 191 | self.try_get(server_port, '') |
michael@0 | 192 | self.try_get(server_port, '?foo=bar') |
michael@0 | 193 | |
michael@0 | 194 | class ProxyTest(unittest.TestCase): |
michael@0 | 195 | |
michael@0 | 196 | def tearDown(self): |
michael@0 | 197 | # reset proxy opener in case it changed |
michael@0 | 198 | urllib2.install_opener(None) |
michael@0 | 199 | |
michael@0 | 200 | def test_proxy(self): |
michael@0 | 201 | docroot = tempfile.mkdtemp() |
michael@0 | 202 | hosts = ('mozilla.com', 'mozilla.org') |
michael@0 | 203 | unproxied_host = 'notmozilla.org' |
michael@0 | 204 | def url(host): return 'http://%s/' % host |
michael@0 | 205 | |
michael@0 | 206 | index_filename = 'index.html' |
michael@0 | 207 | def index_contents(host): return '%s index' % host |
michael@0 | 208 | |
michael@0 | 209 | index = file(os.path.join(docroot, index_filename), 'w') |
michael@0 | 210 | index.write(index_contents('*')) |
michael@0 | 211 | index.close() |
michael@0 | 212 | |
michael@0 | 213 | httpd = mozhttpd.MozHttpd(port=0, docroot=docroot) |
michael@0 | 214 | httpd.start(block=False) |
michael@0 | 215 | server_port = httpd.httpd.server_port |
michael@0 | 216 | |
michael@0 | 217 | proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' % |
michael@0 | 218 | server_port}) |
michael@0 | 219 | urllib2.install_opener(urllib2.build_opener(proxy_support)) |
michael@0 | 220 | |
michael@0 | 221 | for host in hosts: |
michael@0 | 222 | f = urllib2.urlopen(url(host)) |
michael@0 | 223 | try: |
michael@0 | 224 | self.assertEqual(f.getcode(), 200) |
michael@0 | 225 | except AttributeError: |
michael@0 | 226 | pass # python 2.4 |
michael@0 | 227 | self.assertEqual(f.read(), index_contents('*')) |
michael@0 | 228 | |
michael@0 | 229 | httpd.stop() |
michael@0 | 230 | |
michael@0 | 231 | # test separate directories per host |
michael@0 | 232 | |
michael@0 | 233 | httpd = mozhttpd.MozHttpd(port=0, docroot=docroot, proxy_host_dirs=True) |
michael@0 | 234 | httpd.start(block=False) |
michael@0 | 235 | server_port = httpd.httpd.server_port |
michael@0 | 236 | |
michael@0 | 237 | proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' % |
michael@0 | 238 | server_port}) |
michael@0 | 239 | urllib2.install_opener(urllib2.build_opener(proxy_support)) |
michael@0 | 240 | |
michael@0 | 241 | # set up dirs |
michael@0 | 242 | for host in hosts: |
michael@0 | 243 | os.mkdir(os.path.join(docroot, host)) |
michael@0 | 244 | file(os.path.join(docroot, host, index_filename), 'w') \ |
michael@0 | 245 | .write(index_contents(host)) |
michael@0 | 246 | |
michael@0 | 247 | for host in hosts: |
michael@0 | 248 | f = urllib2.urlopen(url(host)) |
michael@0 | 249 | try: |
michael@0 | 250 | self.assertEqual(f.getcode(), 200) |
michael@0 | 251 | except AttributeError: |
michael@0 | 252 | pass # python 2.4 |
michael@0 | 253 | self.assertEqual(f.read(), index_contents(host)) |
michael@0 | 254 | |
michael@0 | 255 | exc = None |
michael@0 | 256 | try: |
michael@0 | 257 | urllib2.urlopen(url(unproxied_host)) |
michael@0 | 258 | except urllib2.HTTPError, e: |
michael@0 | 259 | exc = e |
michael@0 | 260 | self.assertNotEqual(exc, None) |
michael@0 | 261 | self.assertEqual(exc.code, 404) |
michael@0 | 262 | |
michael@0 | 263 | |
michael@0 | 264 | if __name__ == '__main__': |
michael@0 | 265 | unittest.main() |