diff --git a/docs/docs/configuration/index.rst b/docs/docs/configuration/index.rst
index b98154f69..fc9f5d04f 100644
--- a/docs/docs/configuration/index.rst
+++ b/docs/docs/configuration/index.rst
@@ -12,6 +12,7 @@ Moto has a variety of ways to configure the mock behaviour.
environment_variables
recorder/index
+ prettify_responses
state_transition/index
state_transition/models
diff --git a/docs/docs/configuration/prettify_responses.rst b/docs/docs/configuration/prettify_responses.rst
new file mode 100644
index 000000000..e592a380a
--- /dev/null
+++ b/docs/docs/configuration/prettify_responses.rst
@@ -0,0 +1,38 @@
+.. _prettify_responses_page:
+
+.. role:: raw-html(raw)
+ :format: html
+
+=============================
+Prettify responses
+=============================
+
+This option allows to prettify responses from moto. Pretty responses are more readable (eg. for debugging purposes).
+It also makes moto better in mocking AWS as AWS returns prettified responses.
+
+Ugly output:
+
+.. sourcecode:: python
+
+ 178936da-50ad-4d58-8871-22d9979e8658example1lt-d920e32b0cccd6adbexample-name
+
+Prettified output:
+
+.. sourcecode:: python
+
+
+ 178936da-50ad-4d58-8871-22d9979e8658example
+
+ 1
+ lt-d920e32b0cccd6adb
+ example-name
+
+
+
+
+Configuration
+#################
+
+As changing responses can interfere with some external tools, it is disabled by default.
+If you want to enable it, use environment variable:
+`MOTO_PRETTIFY_RESPONSES=True`
\ No newline at end of file
diff --git a/moto/core/responses.py b/moto/core/responses.py
index ac47413a2..432d50b96 100644
--- a/moto/core/responses.py
+++ b/moto/core/responses.py
@@ -18,6 +18,8 @@ from jinja2 import Environment, DictLoader
from typing import Dict, List, Union, Any, Optional
from urllib.parse import parse_qs, parse_qsl, urlparse
from werkzeug.exceptions import HTTPException
+from xml.dom.minidom import parseString as parseXML
+
log = logging.getLogger(__name__)
@@ -104,10 +106,15 @@ class _TemplateEnvironmentMixin(object):
def response_template(self, source):
template_id = self._make_template_id(source)
if not self.contains_template(template_id):
- collapsed = re.sub(
- self.RIGHT_PATTERN, ">", re.sub(self.LEFT_PATTERN, "<", source)
- )
- self.environment.loader.update({template_id: collapsed})
+ if settings.PRETTIFY_RESPONSES:
+ # pretty xml
+ xml = parseXML(source).toprettyxml()
+ else:
+ # collapsed xml
+ xml = re.sub(
+ self.RIGHT_PATTERN, ">", re.sub(self.LEFT_PATTERN, "<", source)
+ )
+ self.environment.loader.update({template_id: xml})
return self.environment.get_template(template_id)
diff --git a/moto/settings.py b/moto/settings.py
index 13e1b2a17..65ceaeb4d 100644
--- a/moto/settings.py
+++ b/moto/settings.py
@@ -29,6 +29,9 @@ ENABLE_KEYPAIR_VALIDATION = bool(
ENABLE_AMI_VALIDATION = bool(os.environ.get("MOTO_ENABLE_AMI_VALIDATION", False))
+PRETTIFY_RESPONSES = bool(os.environ.get("MOTO_PRETTIFY_RESPONSES", False))
+
+
def get_sf_execution_history_type():
"""
Determines which execution history events `get_execution_history` returns
diff --git a/tests/test_core/test_responses.py b/tests/test_core/test_responses.py
index 5f4208486..728f6012d 100644
--- a/tests/test_core/test_responses.py
+++ b/tests/test_core/test_responses.py
@@ -1,3 +1,4 @@
+from unittest import SkipTest, mock
import sure # noqa # pylint: disable=unused-import
from collections import OrderedDict
@@ -6,6 +7,7 @@ from botocore.awsrequest import AWSPreparedRequest
from moto.core.responses import AWSServiceSpec, BaseResponse
from moto.core.responses import flatten_json_request_body
+from moto import settings
def test_flatten_json_request_body():
@@ -205,3 +207,21 @@ def test_response_environment_preserved_by_type():
assert resp_a_new_instance.contains_template(
BaseResponse._make_template_id(source_2)
)
+
+
+@mock.patch(
+ "moto.core.responses.settings.PRETTIFY_RESPONSES",
+ new_callable=mock.PropertyMock(return_value=True),
+)
+def test_jinja_render_prettify(m_env_var):
+ if settings.TEST_SERVER_MODE:
+ raise SkipTest(
+ "It is not possible to set the environment variable in server mode"
+ )
+ response = BaseResponse()
+ TEMPLATE = """Test text"""
+ expected_output = '\n\n\tTest text\n'
+ template = response.response_template(TEMPLATE)
+ xml_string = template.render()
+ assert xml_string == expected_output
+ assert m_env_var