'Send a HTTP request to the Flocker API, return decoded JSON body and
headers.
:param bytes method: HTTP method, e.g. PUT.
:param bytes path: Path to add to base URL.
:param body: If not ``None``, JSON encode this and send as the
body of the request.
:param set success_codes: Expected success response codes.
:param error_codes: Mapping from HTTP response code to exception to be
raised if it is present, or ``None`` to set no errors.
:param configuration_tag: If not ``None``, include value as
``X-If-Configuration-Matches`` header.
:return: ``Deferred`` firing a tuple of (decoded JSON,
response headers).'

def _request_with_headers(self, method, path, body, success_codes, error_codes=None, configuration_tag=None):

    url = (self._base_url + path)
    action = _LOG_HTTP_REQUEST(url=url, method=method, request_body=body)
    if (error_codes is None):
        error_codes = {}
    def error(body, code):
        if (code in error_codes):
            raise error_codes[code](body)
        raise ResponseError(code, body)
    def got_response(response):
        if (response.code in success_codes):
            action.addSuccessFields(response_code=response.code)
            d = json_content(response)
            d.addCallback((lambda decoded_body: (decoded_body, response.headers)))
            return d
        else:
            d = content(response)
            d.addCallback(error, response.code)
            return d
    headers = {'X-Eliot-Task-Id': action.serialize_task_id()}
    data = None
    if (body is not None):
        headers['content-type'] = 'application/json'
        data = dumps(body)
    if (configuration_tag is not None):
        headers['X-If-Configuration-Matches'] = [configuration_tag.encode('utf-8')]
    with action.context():
        request = DeferredContext(self._treq.request(method, url, data=data, headers=headers))
    request.addCallback(got_response)
    def got_body(result):
        action.addSuccessFields(response_body=result[0])
        return result
    request.addCallback(got_body)
    request.addActionFinish()
    return request.result
