Example #1
0
def get_repl_header(conn, ex, mocker):
    req = mocker.spy(franz.miniclient.request, 'makeRequest')
    conn.addTriple(ex.s, ex.p, ex.o)
    # not implemented in Python 2...
    # req.assert_called()
    for _args, kwargs in req.call_args_list:
        headers = normalize_headers(kwargs.get('headers', {})) or {}
        return normalize_repl_header(headers.get('x-repl-settings'))
Example #2
0
def test_commit_settings(conn, ex, mocker):
    req = mocker.spy(franz.miniclient.request, 'makeRequest')
    conn.addTriple(ex.s, ex.p, ex.o)
    conn.commit(durability='quorum')
    # Not available in Python 2
    # req.assert_called()
    args, kwargs = req.call_args
    headers = normalize_headers(kwargs.get('headers', {})) or {}
    header = normalize_repl_header(headers.get('x-repl-settings'))
    assert header == 'durability=quorum'
Example #3
0
def makeRequest(obj,
                method,
                url,
                body=None,
                accept=None,
                contentType=None,
                callback=None,
                errCallback=None,
                headers=None):
    """
    Send an HTTP request to given URL.

    :param obj: A service object containing auth and config information.
    :type obj: franz.miniclient.repository.Service
    :param method: Request method ("GET", "POST", ...).
    :type method: string
    :param url: Target address
    :type url: string
    :param body: Request body (for PUT/POST requests) or query string, optional.
    :type body: basestring|file
    :param accept: Value of the accept header (default: */*)
    :type accept: string
    :param contentType: MIME type of the request body, optional.
    :type contentType: string
    :param callback: Function that will receive the response data.
                     It will be called multiple times per request.
                     The return value should be either None or the number of bytes
                     received, anything else will cause the request to be aborted.
    :type callback: (bytestring) -> int
    :param errCallback: Invoked if the server returned an error.
                        Used only if `callback` is not `None`.
                        The arguments are the response code and
                        the message returned by the server.
                        Unlike normal callback, this is invoked at most once
                        and receives the complete response body.
    :type errCallback: (int, string) -> None
    :param headers: Either a dictionary mapping headers to values or
                    a list of strings that will be included in the request's headers.
    :type headers: Iterable[string] | dict[string, string] | None
    :return: Status code and response body, unless callback is specified (in that case None is returned).
    :rtype: (int, string) | None
    """
    if accept is None:
        accept = "*/*"
    # We create a session object lazily, so we do not have any requests-specific stuff
    # in the implementation of the Service class.
    if obj.session is None:
        obj.session = create_session(obj)
        # Unfortunately our current API does not seem to have a good place
        # to close that explicitly.
        atexit.register(obj.session.close)

    # Encode data as utf-8 if required - requests tries to use ascii now.
    if isinstance(body, unicode_type):
        body = body.encode('utf-8')

    method = method.upper()
    if method in ('PUT', 'POST'):
        data = body
        params = None
    else:
        data = None
        params = body

    # Get the full url
    url = to_native_string(url)
    if not url.startswith("http:") and not url.startswith("https:"):
        url = to_native_string(obj.url) + to_native_string(url)

    # Note that this will create a copy if necessary, so we're not changing the argument
    headers = normalize_headers(headers)
    headers['accept'] = accept
    if contentType:
        headers['content-type'] = contentType
    if obj.runAsName:
        headers['x-masquerade-as-user'] = obj.runAsName

    response = obj.session.request(method,
                                   url,
                                   params=params,
                                   data=data,
                                   headers=headers,
                                   stream=True)
    with contextlib.closing(response):
        if callback is not None:
            if 200 <= response.status_code < 300:
                for chunk in response.iter_content(BUFFER_SIZE):
                    callback_result = callback(chunk)
                    # Simulate curl's behavior
                    if callback_result is not None and callback_result != len(
                            chunk):
                        break
            else:
                if errCallback is None:
                    response.raise_for_status()
                else:
                    errCallback(
                        response.status_code,
                        to_native_string(
                            response.raw.read(decode_content=True)))
        else:
            # Note: no error callback in this case
            return response.status_code, to_native_string(response.content)