Esempio n. 1
0
 def _post_process_response_headers(response: RoutingResponse) -> None:
     """Adjust potential content lengths and checksums after modifying the response."""
     if response.headers and response.content:
         if "Content-Length" in response.headers:
             response.headers["Content-Length"] = str(
                 len(to_bytes(response.content)))
         if "x-amz-crc32" in response.headers:
             response.headers["x-amz-crc32"] = calculate_crc32(
                 response.content)
Esempio n. 2
0
    def return_response(self, method, path, data, headers, response):
        # persist requests to disk
        super(ProxyListenerSQS, self).return_response(method, path, data,
                                                      headers, response)

        if method == "OPTIONS" and path == "/":
            # Allow CORS preflight requests to succeed.
            return 200

        if method != "POST":
            return

        region_name = aws_stack.get_region()
        req_data = parse_request_data(method, path, data)
        action = req_data.get("Action")
        content_str = content_str_original = to_str(response.content)

        if response.status_code >= 400:
            return response

        _fire_event(req_data, response)

        # patch the response and add missing attributes
        if action == "GetQueueAttributes":
            content_str = _add_queue_attributes(path, req_data, content_str,
                                                headers)

        name = r"<Name>\s*RedrivePolicy\s*<\/Name>"
        value = r"<Value>\s*{(.*)}\s*<\/Value>"
        for p1, p2 in ((name, value), (value, name)):
            content_str = re.sub(
                r"<Attribute>\s*%s\s*%s\s*<\/Attribute>" % (p1, p2),
                _fix_redrive_policy,
                content_str,
            )

        # patch the response and return the correct endpoint URLs / ARNs
        if action in (
                "CreateQueue",
                "GetQueueUrl",
                "ListQueues",
                "GetQueueAttributes",
                "ListDeadLetterSourceQueues",
        ):
            if config.USE_SSL and "<QueueUrl>http://" in content_str:
                # return https://... if we're supposed to use SSL
                content_str = re.sub(r"<QueueUrl>\s*http://",
                                     r"<QueueUrl>https://", content_str)
            # expose external hostname:port
            external_port = SQS_PORT_EXTERNAL or get_external_port(headers)
            content_str = re.sub(
                r"<QueueUrl>\s*([a-z]+)://[^<]*:([0-9]+)/([^<]*)\s*</QueueUrl>",
                r"<QueueUrl>\1://%s:%s/\3</QueueUrl>" %
                (config.HOSTNAME_EXTERNAL, external_port),
                content_str,
            )
            # encode account ID in queue URL
            content_str = re.sub(
                r"<QueueUrl>\s*([a-z]+)://([^/]+)/queue/([^<]*)\s*</QueueUrl>",
                r"<QueueUrl>\1://\2/%s/\3</QueueUrl>" %
                constants.TEST_AWS_ACCOUNT_ID,
                content_str,
            )
            # fix queue ARN
            content_str = re.sub(
                r"<([a-zA-Z0-9]+)>\s*arn:aws:sqs:elasticmq:([^<]+)</([a-zA-Z0-9]+)>",
                r"<\1>arn:aws:sqs:%s:\2</\3>" % region_name,
                content_str,
            )

            if action == "CreateQueue":
                regex = r".*<QueueUrl>(.*)</QueueUrl>"
                queue_url = re.match(regex, content_str, re.DOTALL).group(1)
                if SQS_BACKEND_IMPL == "elasticmq":
                    _set_queue_attributes(queue_url, req_data)

        elif action == "SendMessageBatch":
            if validate_empty_message_batch(data, req_data):
                msg = "There should be at least one SendMessageBatchRequestEntry in the request."
                return make_requests_error(code=404,
                                           code_string="EmptyBatchRequest",
                                           message=msg)

        # instruct listeners to process new SQS message
        if action in ("SendMessage", "SendMessageBatch"):
            _process_sent_message(path, req_data, headers, response)

        if content_str_original != content_str:
            # if changes have been made, return patched response
            response.headers["Content-Length"] = len(content_str)
            response.headers["x-amz-crc32"] = calculate_crc32(content_str)
            return requests_response(content_str,
                                     headers=response.headers,
                                     status_code=response.status_code)
Esempio n. 3
0
    def return_response(self, method, path, data, headers, response,
                        request_handler):
        # persist requests to disk
        super(ProxyListenerSQS,
              self).return_response(method, path, data, headers, response,
                                    request_handler)

        if method == 'OPTIONS' and path == '/':
            # Allow CORS preflight requests to succeed.
            return 200

        if method != 'POST':
            return

        region_name = aws_stack.get_region()
        req_data = parse_request_data(method, path, data)
        action = req_data.get('Action')
        content_str = content_str_original = to_str(response.content)

        if response.status_code >= 400:
            return response

        _fire_event(req_data, response)

        # patch the response and add missing attributes
        if action == 'GetQueueAttributes':
            content_str = _add_queue_attributes(path, req_data, content_str,
                                                headers)

        name = r'<Name>\s*RedrivePolicy\s*<\/Name>'
        value = r'<Value>\s*{(.*)}\s*<\/Value>'
        for p1, p2 in ((name, value), (value, name)):
            content_str = re.sub(
                r'<Attribute>\s*%s\s*%s\s*<\/Attribute>' % (p1, p2),
                _fix_redrive_policy, content_str)

        # patch the response and return the correct endpoint URLs / ARNs
        if action in ('CreateQueue', 'GetQueueUrl', 'ListQueues',
                      'GetQueueAttributes', 'ListDeadLetterSourceQueues'):
            if config.USE_SSL and '<QueueUrl>http://' in content_str:
                # return https://... if we're supposed to use SSL
                content_str = re.sub(r'<QueueUrl>\s*http://',
                                     r'<QueueUrl>https://', content_str)
            # expose external hostname:port
            external_port = SQS_PORT_EXTERNAL or get_external_port(
                headers, request_handler)
            content_str = re.sub(
                r'<QueueUrl>\s*([a-z]+)://[^<]*:([0-9]+)/([^<]*)\s*</QueueUrl>',
                r'<QueueUrl>\1://%s:%s/\3</QueueUrl>' %
                (HOSTNAME_EXTERNAL, external_port), content_str)
            # encode account ID in queue URL
            content_str = re.sub(
                r'<QueueUrl>\s*([a-z]+)://([^/]+)/queue/([^<]*)\s*</QueueUrl>',
                r'<QueueUrl>\1://\2/%s/\3</QueueUrl>' %
                constants.TEST_AWS_ACCOUNT_ID, content_str)
            # fix queue ARN
            content_str = re.sub(
                r'<([a-zA-Z0-9]+)>\s*arn:aws:sqs:elasticmq:([^<]+)</([a-zA-Z0-9]+)>',
                r'<\1>arn:aws:sqs:%s:\2</\3>' % region_name, content_str)

            if action == 'CreateQueue':
                queue_url = re.match(r'.*<QueueUrl>(.*)</QueueUrl>',
                                     content_str, re.DOTALL).group(1)
                if SQS_BACKEND_IMPL == 'elasticmq':
                    _set_queue_attributes(queue_url, req_data)

        elif action == 'SendMessageBatch':
            if validate_empty_message_batch(data, req_data):
                msg = 'There should be at least one SendMessageBatchRequestEntry in the request.'
                return make_requests_error(code=404,
                                           code_string='EmptyBatchRequest',
                                           message=msg)

        # instruct listeners to fetch new SQS message
        if action in ('SendMessage', 'SendMessageBatch'):
            _process_sent_message(path, req_data, headers)

        if content_str_original != content_str:
            # if changes have been made, return patched response
            response.headers['content-length'] = len(content_str)
            response.headers['x-amz-crc32'] = calculate_crc32(content_str)
            return requests_response(content_str,
                                     headers=response.headers,
                                     status_code=response.status_code)