prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Return HTTP errors in proper format
  Proposer: Eric Brehault
  Seconder:
  # Motivation
  
  When a page does not exist, or has an error, or is not allowed for the user, Plone returns the appropriate HTTP error (404, 500, ...), and the response is a human readable page, properly skinned, which nice for the user.
  And if the requested resource is not a page (an image, a JS file, an AJAX call, etc.), Plone also returns this human readable page.
  It is useless because the page will not be displayed, and it produces many problems:
  - the response is very heavy,
  - it involves a lot of processing (Plone will render an entire page for nothing),
  - for AJAX call, the response cannot be easily interperted,
  - it might produce a cascade of errors (for instance: the regular response is not supposed to be rendered via Diazo, as it is not an HTML page, but the error is rendered by Diazo, and it might produce another error).
  # Proposed solution
  
  We could display the human readable error page only if the current request `HTTP_ACCEPT` parameter contains `text/html`, in other cases, we would just return a simple JSON error reponse.
  # Proposed implementation
  
  Test the `HTTP_ACCEPT` value in `Products/CMFPlone/skins/plone_templates/standard_error_message.py`, and call the existing template or make a JSON response accordingly.
  # Risks
  
  No identified risks.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `Products/CMFPlone/skins/plone_templates/standard_error_message.py`
  Content:
  ```
  1 ## Script (Python) "standard_error_message"
  2 ##bind container=container
  3 ##bind context=context
  4 ##bind namespace=
  5 ##bind script=script
  6 ##bind subpath=traverse_subpath
  7 ##parameters=**kwargs
  8 ##title=Dispatches to relevant error view
  9 
  10 ## by default we handle everything in 1 PageTemplate.
  11 #  you could easily check for the error_type and
  12 #  dispatch to an appropriate PageTemplate.
  13 
  14 # Check if the object is traversable, if not it might be a view, get its parent
  15 # because we need to render the error on an actual content object
  16 from AccessControl import Unauthorized
  17 try:
  18     while not hasattr(context.aq_explicit, 'restrictedTraverse'):
  19         context = context.aq_parent
  20 except (Unauthorized, AttributeError):
  21     context = context.portal_url.getPortalObject()
  22 
  23 error_type = kwargs.get('error_type', None)
  24 error_message = kwargs.get('error_message', None)
  25 error_log_url = kwargs.get('error_log_url', None)
  26 error_tb = kwargs.get('error_tb', None)
  27 error_traceback = kwargs.get('error_traceback', None)
  28 error_value = kwargs.get('error_value', None)
  29 
  30 if error_log_url:
  31     error_log_id = error_log_url.split('?id=')[1]
  32 else:
  33     error_log_id = None
  34 
  35 
  36 no_actions = {'folder': [], 'user': [], 'global': [], 'workflow': []}
  37 error_page = context.default_error_message(
  38                                 error_type=error_type,
  39                                 error_message=error_message,
  40                                 error_tb=error_tb,
  41                                 error_value=error_value,
  42                                 error_log_url=error_log_url,
  43                                 error_log_id=error_log_id,
  44                                 no_portlets=True,
  45                                 actions=no_actions)
  46 
  47 return error_page
  48
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/Products/CMFPlone/skins/plone_templates/standard_error_message.py b/Products/CMFPlone/skins/plone_templates/standard_error_message.py
  --- a/Products/CMFPlone/skins/plone_templates/standard_error_message.py
  +++ b/Products/CMFPlone/skins/plone_templates/standard_error_message.py
  @@ -27,6 +27,10 @@
   error_traceback = kwargs.get('error_traceback', None)
   error_value = kwargs.get('error_value', None)
   
  +if "text/html" not in context.REQUEST.getHeader('Accept', ''):
  +    context.REQUEST.RESPONSE.setHeader("Content-Type", "application/json")
  +    return '{"error_type": "{0:s}"}'.format(error_type)
  +
   if error_log_url:
       error_log_id = error_log_url.split('?id=')[1]
   else:
  
verification_info: {"golden_diff": "diff --git a/Products/CMFPlone/skins/plone_templates/standard_error_message.py b/Products/CMFPlone/skins/plone_templates/standard_error_message.py\n--- a/Products/CMFPlone/skins/plone_templates/standard_error_message.py\n+++ b/Products/CMFPlone/skins/plone_templates/standard_error_message.py\n@@ -27,6 +27,10 @@\n error_traceback = kwargs.get('error_traceback', None)\n error_value = kwargs.get('error_value', None)\n \n+if \"text/html\" not in context.REQUEST.getHeader('Accept', ''):\n+    context.REQUEST.RESPONSE.setHeader(\"Content-Type\", \"application/json\")\n+    return '{\"error_type\": \"{0:s}\"}'.format(error_type)\n+\n if error_log_url:\n     error_log_id = error_log_url.split('?id=')[1]\n else:\n", "issue": "Return HTTP errors in proper format\nProposer: Eric Brehault\nSeconder:\n# Motivation\n\nWhen a page does not exist, or has an error, or is not allowed for the user, Plone returns the appropriate HTTP error (404, 500, ...), and the response is a human readable page, properly skinned, which nice for the user.\nAnd if the requested resource is not a page (an image, a JS file, an AJAX call, etc.), Plone also returns this human readable page.\nIt is useless because the page will not be displayed, and it produces many problems:\n- the response is very heavy,\n- it involves a lot of processing (Plone will render an entire page for nothing),\n- for AJAX call, the response cannot be easily interperted,\n- it might produce a cascade of errors (for instance: the regular response is not supposed to be rendered via Diazo, as it is not an HTML page, but the error is rendered by Diazo, and it might produce another error).\n# Proposed solution\n\nWe could display the human readable error page only if the current request `HTTP_ACCEPT` parameter contains `text/html`, in other cases, we would just return a simple JSON error reponse.\n# Proposed implementation\n\nTest the `HTTP_ACCEPT` value in `Products/CMFPlone/skins/plone_templates/standard_error_message.py`, and call the existing template or make a JSON response accordingly.\n# Risks\n\nNo identified risks.\n\n", "before_files": [{"content": "## Script (Python) \"standard_error_message\"\n##bind container=container\n##bind context=context\n##bind namespace=\n##bind script=script\n##bind subpath=traverse_subpath\n##parameters=**kwargs\n##title=Dispatches to relevant error view\n\n## by default we handle everything in 1 PageTemplate.\n#  you could easily check for the error_type and\n#  dispatch to an appropriate PageTemplate.\n\n# Check if the object is traversable, if not it might be a view, get its parent\n# because we need to render the error on an actual content object\nfrom AccessControl import Unauthorized\ntry:\n    while not hasattr(context.aq_explicit, 'restrictedTraverse'):\n        context = context.aq_parent\nexcept (Unauthorized, AttributeError):\n    context = context.portal_url.getPortalObject()\n\nerror_type = kwargs.get('error_type', None)\nerror_message = kwargs.get('error_message', None)\nerror_log_url = kwargs.get('error_log_url', None)\nerror_tb = kwargs.get('error_tb', None)\nerror_traceback = kwargs.get('error_traceback', None)\nerror_value = kwargs.get('error_value', None)\n\nif error_log_url:\n    error_log_id = error_log_url.split('?id=')[1]\nelse:\n    error_log_id = None\n\n\nno_actions = {'folder': [], 'user': [], 'global': [], 'workflow': []}\nerror_page = context.default_error_message(\n                                error_type=error_type,\n                                error_message=error_message,\n                                error_tb=error_tb,\n                                error_value=error_value,\n                                error_log_url=error_log_url,\n                                error_log_id=error_log_id,\n                                no_portlets=True,\n                                actions=no_actions)\n\nreturn error_page\n", "path": "Products/CMFPlone/skins/plone_templates/standard_error_message.py"}], "after_files": [{"content": "## Script (Python) \"standard_error_message\"\n##bind container=container\n##bind context=context\n##bind namespace=\n##bind script=script\n##bind subpath=traverse_subpath\n##parameters=**kwargs\n##title=Dispatches to relevant error view\n\n## by default we handle everything in 1 PageTemplate.\n#  you could easily check for the error_type and\n#  dispatch to an appropriate PageTemplate.\n\n# Check if the object is traversable, if not it might be a view, get its parent\n# because we need to render the error on an actual content object\nfrom AccessControl import Unauthorized\ntry:\n    while not hasattr(context.aq_explicit, 'restrictedTraverse'):\n        context = context.aq_parent\nexcept (Unauthorized, AttributeError):\n    context = context.portal_url.getPortalObject()\n\nerror_type = kwargs.get('error_type', None)\nerror_message = kwargs.get('error_message', None)\nerror_log_url = kwargs.get('error_log_url', None)\nerror_tb = kwargs.get('error_tb', None)\nerror_traceback = kwargs.get('error_traceback', None)\nerror_value = kwargs.get('error_value', None)\n\nif \"text/html\" not in context.REQUEST.getHeader('Accept', ''):\n    context.REQUEST.RESPONSE.setHeader(\"Content-Type\", \"application/json\")\n    return '{\"error_type\": \"{0:s}\"}'.format(error_type)\n\nif error_log_url:\n    error_log_id = error_log_url.split('?id=')[1]\nelse:\n    error_log_id = None\n\n\nno_actions = {'folder': [], 'user': [], 'global': [], 'workflow': []}\nerror_page = context.default_error_message(\n                                error_type=error_type,\n                                error_message=error_message,\n                                error_tb=error_tb,\n                                error_value=error_value,\n                                error_log_url=error_log_url,\n                                error_log_id=error_log_id,\n                                no_portlets=True,\n                                actions=no_actions)\n\nreturn error_page\n", "path": "Products/CMFPlone/skins/plone_templates/standard_error_message.py"}]}