httputil_test.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 
00004 from __future__ import absolute_import, division, with_statement
00005 from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders
00006 from tornado.escape import utf8
00007 from tornado.testing import LogTrapTestCase
00008 from tornado.util import b
00009 import logging
00010 import unittest
00011 
00012 
00013 class TestUrlConcat(unittest.TestCase):
00014 
00015     def test_url_concat_no_query_params(self):
00016         url = url_concat(
00017                 "https://localhost/path",
00018                 [('y', 'y'), ('z', 'z')],
00019                 )
00020         self.assertEqual(url, "https://localhost/path?y=y&z=z")
00021 
00022     def test_url_concat_encode_args(self):
00023         url = url_concat(
00024                 "https://localhost/path",
00025                 [('y', '/y'), ('z', 'z')],
00026                 )
00027         self.assertEqual(url, "https://localhost/path?y=%2Fy&z=z")
00028 
00029     def test_url_concat_trailing_q(self):
00030         url = url_concat(
00031                 "https://localhost/path?",
00032                 [('y', 'y'), ('z', 'z')],
00033                 )
00034         self.assertEqual(url, "https://localhost/path?y=y&z=z")
00035 
00036     def test_url_concat_q_with_no_trailing_amp(self):
00037         url = url_concat(
00038                 "https://localhost/path?x",
00039                 [('y', 'y'), ('z', 'z')],
00040                 )
00041         self.assertEqual(url, "https://localhost/path?x&y=y&z=z")
00042 
00043     def test_url_concat_trailing_amp(self):
00044         url = url_concat(
00045                 "https://localhost/path?x&",
00046                 [('y', 'y'), ('z', 'z')],
00047                 )
00048         self.assertEqual(url, "https://localhost/path?x&y=y&z=z")
00049 
00050     def test_url_concat_mult_params(self):
00051         url = url_concat(
00052                 "https://localhost/path?a=1&b=2",
00053                 [('y', 'y'), ('z', 'z')],
00054                 )
00055         self.assertEqual(url, "https://localhost/path?a=1&b=2&y=y&z=z")
00056 
00057     def test_url_concat_no_params(self):
00058         url = url_concat(
00059             "https://localhost/path?r=1&t=2",
00060             [],
00061             )
00062         self.assertEqual(url, "https://localhost/path?r=1&t=2")
00063 
00064 
00065 class MultipartFormDataTest(LogTrapTestCase):
00066     def test_file_upload(self):
00067         data = b("""\
00068 --1234
00069 Content-Disposition: form-data; name="files"; filename="ab.txt"
00070 
00071 Foo
00072 --1234--""").replace(b("\n"), b("\r\n"))
00073         args = {}
00074         files = {}
00075         parse_multipart_form_data(b("1234"), data, args, files)
00076         file = files["files"][0]
00077         self.assertEqual(file["filename"], "ab.txt")
00078         self.assertEqual(file["body"], b("Foo"))
00079 
00080     def test_unquoted_names(self):
00081         # quotes are optional unless special characters are present
00082         data = b("""\
00083 --1234
00084 Content-Disposition: form-data; name=files; filename=ab.txt
00085 
00086 Foo
00087 --1234--""").replace(b("\n"), b("\r\n"))
00088         args = {}
00089         files = {}
00090         parse_multipart_form_data(b("1234"), data, args, files)
00091         file = files["files"][0]
00092         self.assertEqual(file["filename"], "ab.txt")
00093         self.assertEqual(file["body"], b("Foo"))
00094 
00095     def test_special_filenames(self):
00096         filenames = ['a;b.txt',
00097                      'a"b.txt',
00098                      'a";b.txt',
00099                      'a;"b.txt',
00100                      'a";";.txt',
00101                      'a\\"b.txt',
00102                      'a\\b.txt',
00103                      ]
00104         for filename in filenames:
00105             logging.info("trying filename %r", filename)
00106             data = """\
00107 --1234
00108 Content-Disposition: form-data; name="files"; filename="%s"
00109 
00110 Foo
00111 --1234--""" % filename.replace('\\', '\\\\').replace('"', '\\"')
00112             data = utf8(data.replace("\n", "\r\n"))
00113             args = {}
00114             files = {}
00115             parse_multipart_form_data(b("1234"), data, args, files)
00116             file = files["files"][0]
00117             self.assertEqual(file["filename"], filename)
00118             self.assertEqual(file["body"], b("Foo"))
00119 
00120     def test_boundary_starts_and_ends_with_quotes(self):
00121         data = b('''\
00122 --1234
00123 Content-Disposition: form-data; name="files"; filename="ab.txt"
00124 
00125 Foo
00126 --1234--''').replace(b("\n"), b("\r\n"))
00127         args = {}
00128         files = {}
00129         parse_multipart_form_data(b('"1234"'), data, args, files)
00130         file = files["files"][0]
00131         self.assertEqual(file["filename"], "ab.txt")
00132         self.assertEqual(file["body"], b("Foo"))
00133 
00134     def test_missing_headers(self):
00135         data = b('''\
00136 --1234
00137 
00138 Foo
00139 --1234--''').replace(b("\n"), b("\r\n"))
00140         args = {}
00141         files = {}
00142         parse_multipart_form_data(b("1234"), data, args, files)
00143         self.assertEqual(files, {})
00144 
00145     def test_invalid_content_disposition(self):
00146         data = b('''\
00147 --1234
00148 Content-Disposition: invalid; name="files"; filename="ab.txt"
00149 
00150 Foo
00151 --1234--''').replace(b("\n"), b("\r\n"))
00152         args = {}
00153         files = {}
00154         parse_multipart_form_data(b("1234"), data, args, files)
00155         self.assertEqual(files, {})
00156 
00157     def test_line_does_not_end_with_correct_line_break(self):
00158         data = b('''\
00159 --1234
00160 Content-Disposition: form-data; name="files"; filename="ab.txt"
00161 
00162 Foo--1234--''').replace(b("\n"), b("\r\n"))
00163         args = {}
00164         files = {}
00165         parse_multipart_form_data(b("1234"), data, args, files)
00166         self.assertEqual(files, {})
00167 
00168     def test_content_disposition_header_without_name_parameter(self):
00169         data = b("""\
00170 --1234
00171 Content-Disposition: form-data; filename="ab.txt"
00172 
00173 Foo
00174 --1234--""").replace(b("\n"), b("\r\n"))
00175         args = {}
00176         files = {}
00177         parse_multipart_form_data(b("1234"), data, args, files)
00178         self.assertEqual(files, {})
00179 
00180     def test_data_after_final_boundary(self):
00181         # The spec requires that data after the final boundary be ignored.
00182         # http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
00183         # In practice, some libraries include an extra CRLF after the boundary.
00184         data = b("""\
00185 --1234
00186 Content-Disposition: form-data; name="files"; filename="ab.txt"
00187 
00188 Foo
00189 --1234--
00190 """).replace(b("\n"), b("\r\n"))
00191         args = {}
00192         files = {}
00193         parse_multipart_form_data(b("1234"), data, args, files)
00194         file = files["files"][0]
00195         self.assertEqual(file["filename"], "ab.txt")
00196         self.assertEqual(file["body"], b("Foo"))
00197 
00198 
00199 class HTTPHeadersTest(unittest.TestCase):
00200     def test_multi_line(self):
00201         # Lines beginning with whitespace are appended to the previous line
00202         # with any leading whitespace replaced by a single space.
00203         # Note that while multi-line headers are a part of the HTTP spec,
00204         # their use is strongly discouraged.
00205         data = """\
00206 Foo: bar
00207  baz
00208 Asdf: qwer
00209 \tzxcv
00210 Foo: even
00211      more
00212      lines
00213 """.replace("\n", "\r\n")
00214         headers = HTTPHeaders.parse(data)
00215         self.assertEqual(headers["asdf"], "qwer zxcv")
00216         self.assertEqual(headers.get_list("asdf"), ["qwer zxcv"])
00217         self.assertEqual(headers["Foo"], "bar baz,even more lines")
00218         self.assertEqual(headers.get_list("foo"), ["bar baz", "even more lines"])
00219         self.assertEqual(sorted(list(headers.get_all())),
00220                          [("Asdf", "qwer zxcv"),
00221                           ("Foo", "bar baz"),
00222                           ("Foo", "even more lines")])


rosbridge_server
Author(s): Jonathan Mace
autogenerated on Thu Jan 2 2014 11:53:55