def test_from_responsecaplarge(self):
     response = mock.NonCallableMagicMock(spec=requests.Response)
     response.headers = {
         'content-type': 'Multipart/Related; boundary="samp1"'
     }
     cnt = io.BytesIO()
     cnt.write(b'\r\n--samp1\r\n')
     cnt.write(b'Header-1: Header-Value-1\r\n')
     cnt.write(b'Header-2: Header-Value-2\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 1, Line 1\r\n')
     cnt.write(b'Body 1, Line 2\r\n')
     cnt.write(b'--samp1\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 2, Line 1\r\n')
     cnt.write(b'--samp1--\r\n')
     response.content = cnt.getvalue()
     decoder_2 = MultipartDecoder.from_response(response)
     assert decoder_2.content_type == response.headers['content-type']
     assert (
         decoder_2.parts[0].content == b'Body 1, Line 1\r\nBody 1, Line 2'
     )
     assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
     assert len(decoder_2.parts[1].headers) == 0
     assert decoder_2.parts[1].content == b'Body 2, Line 1'
 def test_from_response(self):
     response = mock.NonCallableMagicMock(spec=requests.Response)
     response.headers = {
         'content-type': 'multipart/related; boundary="samp1"'
     }
     cnt = io.BytesIO()
     cnt.write(b'\r\n--samp1\r\n')
     cnt.write(b'Header-1: Header-Value-1\r\n')
     cnt.write(b'Header-2: Header-Value-2\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 1, Line 1\r\n')
     cnt.write(b'Body 1, Line 2\r\n')
     cnt.write(b'--samp1\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 2, Line 1\r\n')
     cnt.write(b'--samp1--\r\n')
     response.content = cnt.getvalue()
     decoder_2 = MultipartDecoder.from_response(response)
     assert decoder_2.content_type == response.headers['content-type']
     assert (
         decoder_2.parts[0].content == b'Body 1, Line 1\r\nBody 1, Line 2'
     )
     assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
     assert len(decoder_2.parts[1].headers) == 0
     assert decoder_2.parts[1].content == b'Body 2, Line 1'
Example #3
0
    def test_uploadhelper(self):
        file = io.BytesIO(b"I'm a file, yes I am!")
        response = ('{"got":[{"filename":"afile",'
                    '"fileref":"sha224-aaaabbbb"}]}')

        mock = requests_mock.Mocker()
        mock.post('https://example.com/perkeep/', text=response)

        with mock:
            fileref = self.uploadhelper.upload_file('afile', file,
                                                    '2010-01-02T10:20:30Z')

        self.assertEqual(fileref, 'sha224-aaaabbbb')

        decoder = MultipartDecoder(mock.last_request.body,
                                   mock.last_request.headers['Content-Type'])

        found_modtime, found_file = False, False

        for part in decoder.parts:
            if b'modtime' in part.headers[b'Content-Disposition']:
                self.assertEqual(part.content, b'2010-01-02T10:20:30Z')
                found_modtime = True

            elif b'afile' in part.headers[b'Content-Disposition']:
                self.assertEqual(part.content, b"I'm a file, yes I am!")
                found_file = True

        self.assertTrue(found_modtime,
                        'modtime was not found in multipart data')
        self.assertTrue(found_file, 'file was not found in multipart data')
Example #4
0
def test_rebuild_xml():
    data = "\r\n".join(line.strip() for line in """
        --MIME_boundary
        Content-Type: application/soap+xml; charset=UTF-8
        Content-Transfer-Encoding: 8bit
        Content-ID: <*****@*****.**>

        <soap:Envelope
        xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
        xmlns:xop='http://www.w3.org/2004/08/xop/include'
        xmlns:xop-mime='http://www.w3.org/2005/05/xmlmime'>
        <soap:Body>
        <submitClaim>
        <accountNumber>5XJ45-3B2</accountNumber>
        <eventType>accident</eventType>
        <image xop-mime:content-type='image/jpeg'><xop:Include href="cid:[email protected]"/></image>
        </submitClaim>
        </soap:Body>
        </soap:Envelope>

        --MIME_boundary
        Content-Type: image/jpeg
        Content-Transfer-Encoding: binary
        Content-ID: <*****@*****.**>

        ...binary JPG image...

        --MIME_boundary--
    """.splitlines()).encode("utf-8")

    response = stub(
        status_code=200,
        content=data,
        encoding=None,
        headers={
            "Content-Type":
            'multipart/related; boundary=MIME_boundary; type="application/soap+xml"; start="<*****@*****.**>" 1'
        },
    )

    decoder = MultipartDecoder(response.content,
                               response.headers["Content-Type"], "utf-8")

    document = etree.fromstring(decoder.parts[0].content)
    message_pack = MessagePack(parts=decoder.parts[1:])
    xop.process_xop(document, message_pack)

    expected = """
        <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xop-mime="http://www.w3.org/2005/05/xmlmime">
          <soap:Body>
            <submitClaim>
            <accountNumber>5XJ45-3B2</accountNumber>
            <eventType>accident</eventType>
            <image xop-mime:content-type="image/jpeg">Li4uYmluYXJ5IEpQRyBpbWFnZS4uLg==</image>
            </submitClaim>
          </soap:Body>
        </soap:Envelope>
    """
    assert_nodes_equal(etree.tostring(document), expected)
Example #5
0
    def process_reply(self, client, operation, response):
        """Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        """
        if response.status_code != 200 and not response.content:
            raise TransportError(
                u'Server returned HTTP status %d (no content available)'
                % response.status_code)

        content_type = response.headers.get('Content-Type', 'text/xml')
        media_type = get_media_type(content_type)
        message_pack = None

        if media_type == 'multipart/related':
            decoder = MultipartDecoder(
                response.content, content_type, response.encoding or 'utf-8')

            content = decoder.parts[0].content
            if len(decoder.parts) > 1:
                message_pack = MessagePack(parts=decoder.parts[1:])
        else:
            content = response.content

        try:
            doc = parse_xml(
                content, self.transport,
                strict=client.wsdl.strict,
                xml_huge_tree=client.xml_huge_tree)
        except XMLSyntaxError:
            raise TransportError(
                u'Server returned HTTP status %d (%s)'
                % (response.status_code, response.content))

        if client.wsse:
            client.wsse.verify(doc)

        doc, http_headers = plugins.apply_ingress(
            client, doc, response.headers, operation)

        # If the response code is not 200 or if there is a Fault node available
        # then assume that an error occured.
        fault_node = doc.find(
            'soap-env:Body/soap-env:Fault', namespaces=self.nsmap)
        if response.status_code != 200 or fault_node is not None:
            return self.process_error(doc, operation)

        result = operation.process_reply(doc)

        if message_pack:
            message_pack._set_root(result)
            return message_pack
        return result
Example #6
0
def test_file_is_being_encoded():
    """Test if file is being encoded."""
    data = bytes([0x13] * 1024)

    stream = StreamWrapper(BytesIO(data), 1024)

    form = _multipart_encoder('test', stream, 'application/x-binary')
    response_data = form.read()
    decoder = MultipartDecoder(response_data, form.content_type)

    assert decoder.parts[0].content == data
Example #7
0
 def setUp(self):
     self.sample_1 = (
         ('field 1', 'value 1'),
         ('field 2', 'value 2'),
         ('field 3', 'value 3'),
         ('field 4', 'value 4'),
     )
     self.boundary = 'test boundary'
     self.encoded_1 = MultipartEncoder(self.sample_1, self.boundary)
     self.decoded_1 = MultipartDecoder(self.encoded_1.to_string(),
                                       self.encoded_1.content_type)
Example #8
0
def UnpackMultipartRequest(environ) :
    """Unpack a multipart request
    """

    request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    request_type = environ.get('CONTENT_TYPE','')
    if not request_type.startswith('multipart/form-data') :
        msg = 'unknown request type, <{0}>'.format(request_type)
        raise Exception(msg)

    request_body = environ['wsgi.input'].read(request_body_size)
    return MultipartDecoder(request_body, request_type)
    def _eval_adhoc(self, lang, line, cell):
        self._check_for_session()

        valid_lang = ("xquery", "javascript")
        if lang not in valid_lang:
            raise TypeError("lang can only be " + ", ".join(valid_lang))
        
        args = shlex.split(line, comments = True)
        self._check_invalid_args(args, ("-raw", "-dataframe"))
        output_opt = "default"
        if "-raw" in args:
            output_opt = "raw"
        if "-dataframe" in args:
            output_opt = "dataframe"
        
        # execute code on MarkLogic
        url = self.session_baseurl + "/v1/eval"
        body = {
            lang: cell
        }
        output = []
        response = self.session.post(url, data = body)
        if response.status_code == 200:
            headers = { header.lower(): value for (header, value) in response.headers.items() } 
            # as per docs, /v1/eval should always return multipart/mixed
            if "content-type" in headers and headers["content-type"].startswith("multipart/mixed"):
                mp_data = MultipartDecoder.from_response(response)
                for part in mp_data.parts:
                    part_headers = { header.decode("utf-8").lower(): value.decode("utf-8") for (header, value) in part.headers.items() } 
                    part_content_type = part_headers["content-type"]
                    part_x_primitive = part_headers["x-primitive"]
                    part_content = part.content.decode("utf-8")
                    data = part_content if output_opt == "raw" else self._parse_content(part_content, part_content_type, part_x_primitive)
                    output.append(data)
        else:
            raise EvalError("Request to %s returned %s %s: %s" % (url, response.status_code, response.reason, response.text))

        output = output[0] if len(output) == 1 else output
        if output_opt == "dataframe":
            try:
                output = pandas.DataFrame(output) # try to fit into a dataframe, may raise an exception depending on result's shape
            except:
                raise CoercionError("Unable to fit response into a DataFrame")
        return {
            "status_code": response.status_code,
            "output": output,
            "output_opt": output_opt,
            "args": args
        }
Example #10
0
def parse_multipart(response: Response_) -> Sequence[Any]:
    """
    RFC 2045 describes the format of an Internet message body containing a MIME message. The
    body contains one or more body parts, each preceded by a boundary delimiter line, and the
    last one followed by a closing boundary delimiter line. After its boundary delimiter line,
    each body part then consists of a header area, a blank line, and a body area.

    HTTP/1.1 200 OK
    Server: Apache/2.0.13
    Date: Fri, 22 OCT 2004 12:03:38 GMT
    Cache-Control: private
    RETS-Version: RETS/1.7.2
    MIME-Version: 1.0
    Content-Type: multipart/parallel; boundary="simple boundary"

    --simple boundary
    Content-Type: image/jpeg
    Content-ID: 123456
    Object-ID: 1

    <binary data>

    --simple boundary
    Content-Type: text/xml
    Content-ID: 123457
    Object-ID: 1

    <RETS ReplyCode="20403" ReplyText="There is no listing with that ListingID"/>

    --simple boundary--
    """
    multipart = MultipartDecoder.from_response(response, response.encoding)
    # We need to decode the headers because MultipartDecoder returns bytes keys and values,
    # while requests.Response.headers uses str keys and values.
    for part in multipart.parts:
        part.headers = _decode_headers(part.headers, response.encoding)

    def parse_multipart(parts):
        for part in parts:
            try:
                yield parse_response(part)
            except RetsApiError as e:
                if e.reply_code != 20403:  # No object found
                    raise

    return tuple(parse_multipart(multipart.parts))
Example #11
0
def _parse_multipart(response: ResponseLike,
                     parser: Parser) -> Sequence[Object]:
    """
    RFC 2045 describes the format of an Internet message body containing a MIME message. The
    body contains one or more body parts, each preceded by a boundary delimiter line, and the
    last one followed by a closing boundary delimiter line. After its boundary delimiter line,
    each body part then consists of a header area, a blank line, and a body area.

    HTTP/1.1 200 OK
    Server: Apache/2.0.13
    Date: Fri, 22 OCT 2004 12:03:38 GMT
    Cache-Control: private
    RETS-Version: RETS/1.7.2
    MIME-Version: 1.0
    Content-Type: multipart/parallel; boundary="simple boundary"

    --simple boundary
    Content-Type: image/jpeg
    Content-ID: 123456
    Object-ID: 1

    <binary data>

    --simple boundary
    Content-Type: text/xml
    Content-ID: 123457
    Object-ID: 1

    <RETS ReplyCode="20403" ReplyText="There is no listing with that ListingID"/>

    --simple boundary--
    """
    encoding = response.encoding or DEFAULT_ENCODING
    multipart = MultipartDecoder.from_response(response, encoding)
    # We need to decode the headers because MultipartDecoder returns bytes keys and values,
    # while requests.Response.headers uses str keys and values.
    for part in multipart.parts:
        part.headers = _decode_headers(part.headers, encoding)

    objects = (_parse_body_part(part, parser) for part in multipart.parts)
    return tuple(object_ for object_ in objects if object_ is not None)
Example #12
0
    def get_blocks(self, block_ids):
        """Get a list of blocks from the storage service using the get blocks
        interface, block ids should be base64 encoded

        :param block_ids: list of base64 encoded strings
        :returns list of strings: list of byte strings containing block data
        """
        request_identifier = self.request_identifier
        request_headers = {
            'x-request-identifier': 'request{0}'.format(request_identifier)
        }

        url = "{0}/block/gets".format(self.ServiceURL)
        try:
            response = self.session.post(url,
                                         json=block_ids,
                                         timeout=self.default_timeout)
        except Exception as e:
            logger.warn('unknown exception (get_blocks); %s', str(e))
            raise StorageException(str(e)) from e

        response.raise_for_status()

        try:
            # decode the response, note that we put the multipart encoding into a
            # customer header because urllib3 doesn't seem to like requests.toolbelt's
            # multipart encoding
            mp_decoder = MultipartDecoder(response.content,
                                          response.headers['x-content-type'])

            block_data_list = []
            for part in mp_decoder.parts:
                block_data_list.append(part.content)

            return block_data_list
        except Exception as e:
            logger.warn('unknown exception (get_blocks); %s', str(e))
            raise StorageException(str(e)) from e
Example #13
0
    def process_reply(self, client, operation, response):
        """Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        """
        if response.status_code in (201, 202) and not response.content:
            return None

        elif response.status_code != 200 and not response.content:
            raise TransportError(
                u"Server returned HTTP status %d (no content available)"
                % response.status_code,
                status_code=response.status_code,
            )

        content_type = response.headers.get("Content-Type", "text/xml")
        media_type = get_media_type(content_type)
        message_pack = None

        # If the reply is a multipart/related then we need to retrieve all the
        # parts
        if media_type == "multipart/related":
            decoder = MultipartDecoder(
                response.content, content_type, response.encoding or "utf-8"
            )
            content = decoder.parts[0].content
            if len(decoder.parts) > 1:
                message_pack = MessagePack(parts=decoder.parts[1:])
        else:
            content = response.content

        try:
            doc = parse_xml(content, self.transport, settings=client.settings)
        except XMLSyntaxError as exc:
            raise TransportError(
                "Server returned response (%s) with invalid XML: %s.\nContent: %r"
                % (response.status_code, exc, response.content),
                status_code=response.status_code,
                content=response.content,
            )

        # Check if this is an XOP message which we need to decode first
        if message_pack:
            if process_xop(doc, message_pack):
                message_pack = None

        if client.wsse:
            client.wsse.verify(doc)

        doc, http_headers = plugins.apply_ingress(
            client, doc, response.headers, operation
        )

        # If the response code is not 200 or if there is a Fault node available
        # then assume that an error occured.
        fault_node = doc.find("soap-env:Body/soap-env:Fault", namespaces=self.nsmap)
        if response.status_code != 200 or fault_node is not None:
            return self.process_error(doc, operation)

        result = operation.process_reply(doc)

        if message_pack:
            message_pack._set_root(result)
            return message_pack
        return result
 def test_non_multipart_response_fails(self):
     jpeg_response = mock.NonCallableMagicMock(spec=requests.Response)
     jpeg_response.headers = {'content-type': 'image/jpeg'}
     with pytest.raises(NonMultipartContentTypeException):
         MultipartDecoder.from_response(jpeg_response)
Example #15
0
 def test_non_multipart_response_fails(self):
     jpeg_response = mock.NonCallableMagicMock(spec=requests.Response)
     jpeg_response.headers = {'content-type': 'image/jpeg'}
     with pytest.raises(NonMultipartContentTypeException):
         MultipartDecoder.from_response(jpeg_response)