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)
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)
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)