Exemple #1
0
 def test_encode_multipart_data_list_params(self):
     params_in = [("one", ["ABC", "XYZ"]), ("one", "UVW")]
     body, headers = encode_multipart_data(params_in, [])
     params_out, files_out = self.parse_headers_and_body_with_django(
         headers, body)
     self.assertEqual({"one": ["ABC", "XYZ", "UVW"]}, params_out)
     self.assertSetEqual(set(), set(files_out))
Exemple #2
0
 def test_encode_multipart_data_multiple_params(self):
     # Sequences of parameters and files can be passed to
     # encode_multipart_data() so that multiple parameters/files with the
     # same name can be provided.
     params_in = [
         ("one", "ABC"),
         ("one", "XYZ"),
         ("two", "DEF"),
         ("two", "UVW"),
     ]
     files_in = [
         ("f-one", BytesIO(urandom(32))),
         ("f-two", BytesIO(urandom(32))),
     ]
     body, headers = encode_multipart_data(params_in, files_in)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(headers["Content-Type"],
                     StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     params_out, files_out = (parse_headers_and_body_with_django(
         headers, body))
     params_out_expected = MultiValueDict()
     for name, value in params_in:
         params_out_expected.appendlist(name, value)
     self.assertEqual(params_out_expected, params_out, ahem_django_ahem)
     self.assertSetEqual({"f-one", "f-two"}, set(files_out))
     files_expected = {name: buf.getvalue() for name, buf in files_in}
     files_observed = {name: buf.read() for name, buf in files_out.items()}
     self.assertEqual(files_expected, files_observed, ahem_django_ahem)
Exemple #3
0
 def test_encode_multipart_data_multiple_params(self):
     # Sequences of parameters and files can be passed to
     # encode_multipart_data() so that multiple parameters/files with the
     # same name can be provided.
     params_in = [
         ("one", "ABC"),
         ("one", "XYZ"),
         ("two", "DEF"),
         ("two", "UVW"),
         ]
     files_in = [
         ("f-one", BytesIO(urandom(32))),
         ("f-two", BytesIO(urandom(32))),
         ]
     body, headers = encode_multipart_data(params_in, files_in)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(
         headers["Content-Type"],
         StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     params_out, files_out = (
         parse_headers_and_body_with_django(headers, body))
     params_out_expected = MultiValueDict()
     for name, value in params_in:
         params_out_expected.appendlist(name, value)
     self.assertEqual(
         params_out_expected, params_out,
         ahem_django_ahem)
     self.assertSetEqual({"f-one", "f-two"}, set(files_out))
     files_expected = {name: buf.getvalue() for name, buf in files_in}
     files_observed = {name: buf.read() for name, buf in files_out.items()}
     self.assertEqual(
         files_expected, files_observed,
         ahem_django_ahem)
Exemple #4
0
    def test__get_response_restores_files_across_requests(self):
        handler = views.WebApplicationHandler(3)
        file_content = sample_binary_data
        file_name = 'content'

        recorder = []

        def get_response_read_content_files(self, request):
            # Simple get_response method which returns the 'file_name' file
            # from the request in the response.
            content = request.FILES[file_name].read()
            # Record calls.
            recorder.append(content)
            response = HttpResponse(content=content,
                                    content_type=b"text/plain; charset=utf-8")
            handler._WebApplicationHandler__retry.add(response)
            return response

        self.patch(WSGIHandler, "get_response",
                   get_response_read_content_files)

        body, headers = encode_multipart_data(
            [], [[file_name, io.BytesIO(file_content)]])
        env = {
            'REQUEST_METHOD': 'POST',
            'wsgi.input': wsgi._InputStream(io.BytesIO(body.encode("utf-8"))),
            'CONTENT_TYPE': headers['Content-Type'],
            'CONTENT_LENGTH': headers['Content-Length'],
            'HTTP_MIME_VERSION': headers['MIME-Version'],
        }
        request = make_request(env)

        response = handler.get_response(request)
        self.assertEqual(file_content, response.content)
        self.assertEqual(recorder, [file_content] * 3)
 def test_encode_multipart_data_multiple_params(self):
     # Sequences of parameters and files passed to
     # encode_multipart_data() permit use of the same name for
     # multiple parameters and/or files. See `make_payloads` to
     # understand how it processes different types of parameter
     # values.
     params_in = [
         ("one", "ABC"),
         ("one", "XYZ"),
         ("two", ["DEF", "UVW"]),
     ]
     files_in = [
         ("f-one", BytesIO(b"f1")),
         ("f-two", open(self.make_file(contents=b"f2"), "rb")),
         ("f-three", lambda: open(self.make_file(contents=b"f3"), "rb")),
     ]
     body, headers = encode_multipart_data(params_in, files_in)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(headers["Content-Type"],
                     StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     params_out, files_out = (parse_headers_and_body_with_django(
         headers, body))
     params_out_expected = MultiValueDict()
     params_out_expected.appendlist("one", "ABC")
     params_out_expected.appendlist("one", "XYZ")
     params_out_expected.appendlist("two", "DEF")
     params_out_expected.appendlist("two", "UVW")
     self.assertEqual(params_out_expected, params_out, ahem_django_ahem)
     files_expected = {"f-one": b"f1", "f-two": b"f2", "f-three": b"f3"}
     files_observed = {name: buf.read() for name, buf in files_out.items()}
     self.assertEqual(files_expected, files_observed, ahem_django_ahem)
Exemple #6
0
    def prepare_payload(op, method, uri, data):
        """Return the URI (modified perhaps) and body and headers.

        - For GET requests, encode parameters in the query string.

        - Otherwise always encode parameters in the request body.

        - Except op; this can always go in the query string.

        :param method: The HTTP method.
        :param uri: The URI of the action.
        :param data: A dict or iterable of name=value pairs to pack into the
            body or headers, depending on the type of request.
        """
        if method == "GET":
            query = data if op is None else chain([("op", op)], data)
            body, headers = None, {}
        else:
            query = [] if op is None else [("op", op)]
            if data:
                body, headers = encode_multipart_data(data)
            else:
                body, headers = None, {}

        uri = urlparse(uri)._replace(query=urlencode(query)).geturl()
        return uri, body, headers
Exemple #7
0
    def prepare_payload(op, method, uri, data):
        """Return the URI (modified perhaps) and body and headers.

        - For GET requests, encode parameters in the query string.

        - Otherwise always encode parameters in the request body.

        - Except op; this can always go in the query string.

        :param method: The HTTP method.
        :param uri: The URI of the action.
        :param data: A dict or iterable of name=value pairs to pack into the
            body or headers, depending on the type of request.
        """
        if method == "GET":
            query = data if op is None else chain([("op", op)], data)
            body, headers = None, {}
        else:
            query = [] if op is None else [("op", op)]
            if data:
                body, headers = encode_multipart_data(data)
            else:
                body, headers = None, {}

        uri = urlparse(uri)._replace(query=urlencode(query)).geturl()
        return uri, body, headers
Exemple #8
0
 def test_encode_multipart_data_produces_str(self):
     data = {factory.make_string(): factory.make_string().encode("ascii")}
     files = {
         factory.make_string():
         (BytesIO(factory.make_string().encode("ascii")))
     }
     body, headers = encode_multipart_data(data, files)
     self.assertIsInstance(body, str)
Exemple #9
0
 def test_encode_multipart_data_list_params(self):
     params_in = [
         ("one", ["ABC", "XYZ"]),
         ("one", "UVW"),
         ]
     body, headers = encode_multipart_data(params_in, [])
     params_out, files_out = (
         parse_headers_and_body_with_django(headers, body))
     self.assertEqual({'one': ['ABC', 'XYZ', 'UVW']}, params_out)
     self.assertSetEqual(set(), set(files_out))
 def test_encode_multipart_data_produces_bytes(self):
     data = {
         factory.make_string(): factory.make_string().encode('ascii'),
     }
     files = {
         factory.make_string(): (
             BytesIO(factory.make_string().encode('ascii'))),
     }
     body, headers = encode_multipart_data(data, files)
     self.assertIsInstance(body, bytes)
Exemple #11
0
 def test_encode_multipart_data_produces_bytes(self):
     data = {
         factory.getRandomString():
         (factory.getRandomString().encode('ascii')),
     }
     files = {
         factory.getRandomString():
         (BytesIO(factory.getRandomString().encode('ascii'))),
     }
     body, headers = encode_multipart_data(data, files)
     self.assertIsInstance(body, bytes)
 def test_encode_multipart_data(self):
     # The encode_multipart_data() function should take a list of
     # parameters and files and encode them into a MIME
     # multipart/form-data suitable for posting to the MAAS server.
     params = {"op": "add", "foo": "bar\u1234"}
     random_data = urandom(32)
     files = {"baz": BytesIO(random_data)}
     body, headers = encode_multipart_data(params, files)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(headers["Content-Type"],
                     StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     post, files = parse_headers_and_body_with_django(headers, body)
     self.assertEqual({name: [value]
                       for name, value in params.items()}, post,
                      ahem_django_ahem)
     self.assertSetEqual({"baz"}, set(files))
     self.assertEqual(random_data, files["baz"].read(), ahem_django_ahem)
Exemple #13
0
 def test_encode_multipart_data(self):
     # The encode_multipart_data() function should take a list of
     # parameters and files and encode them into a MIME
     # multipart/form-data suitable for posting to the MAAS server.
     params = {"op": "add", "foo": "bar\u1234"}
     random_data = urandom(32)
     files = {"baz": BytesIO(random_data)}
     body, headers = encode_multipart_data(params, files)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(
         headers["Content-Type"],
         StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     post, files = parse_headers_and_body_with_django(headers, body)
     self.assertEqual(
         {name: [value] for name, value in params.items()}, post,
         ahem_django_ahem)
     self.assertSetEqual({"baz"}, set(files))
     self.assertEqual(
         random_data, files["baz"].read(),
         ahem_django_ahem)
 def test_encode_multipart_data_multiple_params(self):
     # Sequences of parameters and files passed to
     # encode_multipart_data() permit use of the same name for
     # multiple parameters and/or files. See `make_payloads` to
     # understand how it processes different types of parameter
     # values.
     params_in = [
         ("one", "ABC"),
         ("one", "XYZ"),
         ("two", ["DEF", "UVW"]),
         ]
     files_in = [
         ("f-one", BytesIO(b"f1")),
         ("f-two", open(self.make_file(contents=b"f2"), "rb")),
         ("f-three", lambda: open(self.make_file(contents=b"f3"), "rb")),
         ]
     body, headers = encode_multipart_data(params_in, files_in)
     self.assertEqual("%s" % len(body), headers["Content-Length"])
     self.assertThat(
         headers["Content-Type"],
         StartsWith("multipart/form-data; boundary="))
     # Round-trip through Django's multipart code.
     params_out, files_out = (
         parse_headers_and_body_with_django(headers, body))
     params_out_expected = MultiValueDict()
     params_out_expected.appendlist("one", "ABC")
     params_out_expected.appendlist("one", "XYZ")
     params_out_expected.appendlist("two", "DEF")
     params_out_expected.appendlist("two", "UVW")
     self.assertEqual(
         params_out_expected, params_out,
         ahem_django_ahem)
     files_expected = {"f-one": b"f1", "f-two": b"f2", "f-three": b"f3"}
     files_observed = {name: buf.read() for name, buf in files_out.items()}
     self.assertEqual(
         files_expected, files_observed,
         ahem_django_ahem)
Exemple #15
0
    def _formulate_change(self, path, params, as_json=False):
        """Return URL, headers, and body for a non-GET request.

        This is similar to _formulate_get, except parameters are encoded as
        a multipart form body.

        :param path: Path to the object to issue a GET on.
        :param params: A dict of parameter values.
        :param as_json: Encode params as application/json instead of
            multipart/form-data. Only use this if you know the API already
            supports JSON requests.
        :return: A tuple: URL, headers, and body for the request.
        """
        url = self._make_url(path)
        if "op" in params:
            params = dict(params)
            op = params.pop("op")
            url += "?" + urlencode([("op", op)])
        if as_json:
            body, headers = encode_json_data(params)
        else:
            body, headers = encode_multipart_data(params, {})
        self.auth.sign_request(url, headers)
        return url, headers, body
Exemple #16
0
    def _formulate_change(self, path, params, as_json=False):
        """Return URL, headers, and body for a non-GET request.

        This is similar to _formulate_get, except parameters are encoded as
        a multipart form body.

        :param path: Path to the object to issue a GET on.
        :param params: A dict of parameter values.
        :param as_json: Encode params as application/json instead of
            multipart/form-data. Only use this if you know the API already
            supports JSON requests.
        :return: A tuple: URL, headers, and body for the request.
        """
        url = self._make_url(path)
        if 'op' in params:
            params = dict(params)
            op = params.pop('op')
            url += '?' + urlencode([('op', op)])
        if as_json:
            body, headers = encode_json_data(params)
        else:
            body, headers = encode_multipart_data(params, {})
        self.auth.sign_request(url, headers)
        return url, headers, body
Exemple #17
0
 def test_encode_multipart_data_closes_with_closing_boundary_line(self):
     data = {b'foo': factory.getRandomString().encode('ascii')}
     files = {b'bar': BytesIO(factory.getRandomString().encode('ascii'))}
     body, headers = encode_multipart_data(data, files)
     self.assertThat(body, EndsWith(b'--'))
 def test_encode_multipart_data_closes_with_closing_boundary_line(self):
     data = {b'foo': factory.make_string().encode('ascii')}
     files = {b'bar': BytesIO(factory.make_string().encode('ascii'))}
     body, headers = encode_multipart_data(data, files)
     self.assertThat(body, EndsWith(b'--'))
Exemple #19
0
 def test_encode_multipart_data_closes_with_closing_boundary_line(self):
     data = {"foo": factory.make_string().encode("ascii")}
     files = {"bar": BytesIO(factory.make_string().encode("ascii"))}
     body, headers = encode_multipart_data(data, files)
     self.assertThat(body, EndsWith("--"))