Fetch (and cache) the request body as a dictionary.

        :raise web.HTTPError:
            - if the content type cannot be matched, then the status code
              is set to 415 Unsupported Media Type.
            - if decoding the content body fails, then the status code is
              set to 400 Bad Syntax.

def get_request_body(self):
        """
        Fetch (and cache) the request body as a dictionary.

        :raise web.HTTPError:
            - if the content type cannot be matched, then the status code
              is set to 415 Unsupported Media Type.
            - if decoding the content body fails, then the status code is
              set to 400 Bad Syntax.

        """
        if self._request_body is None:
            settings = get_settings(self.application, force_instance=True)
            content_type_header = headers.parse_content_type(
                self.request.headers.get('Content-Type',
                                         settings.default_content_type))
            content_type = '/'.join([content_type_header.content_type,
                                     content_type_header.content_subtype])
            if content_type_header.content_suffix is not None:
                content_type = '+'.join([content_type,
                                         content_type_header.content_suffix])
            try:
                handler = settings[content_type]
            except KeyError:
                raise web.HTTPError(415, 'cannot decode body of type %s',
                                    content_type)

            try:
                self._request_body = handler.from_bytes(self.request.body)
            except Exception:
                self._logger.exception('failed to decode request body')
                raise web.HTTPError(400, 'failed to decode request')

        return self._request_body