Skip to content

Streamed uploads fail against local httpbin #33

@jkbrzt

Description

@jkbrzt

Against the local httpbin It fails every time and the failuire has two flavours (see bellow).

Relevant: https://github.com/kennethreitz/requests/issues/2422

test.py

import sys
import requests


def stream():
    yield b'ham'
    yield b'spam'


def test_stream():
    r = requests.post('http://httpbin.org/post', data=stream())
    assert r.json()['data'] == 'hamspam'


def test_stream_local_httpbin(httpbin):
    r = requests.post(httpbin.url + '/post', data=stream())
    assert r.json()['data'] == 'hamspam'

body missing:

$ py.test test.py
===================================================== test session starts ======================================================
platform darwin -- Python 3.5.1, pytest-2.9.0, py-1.4.31, pluggy-0.3.1
rootdir: /private/tmp, inifile:
plugins: cov-2.2.1, httpbin-0.2.3
collected 2 items

test.py .F

=========================================================== FAILURES ===========================================================
__________________________________________________ test_stream_local_httpbin ___________________________________________________

httpbin = <Server(<class 'pytest_httpbin.serve.Server'>, started 123145309245440)>

    def test_stream_local_httpbin(httpbin):
        r = requests.post(httpbin.url + '/post', data=stream())
>       assert r.json()['data'] == 'hamspam'
E       assert '' == 'hamspam'
E         + hamspam

test.py:17: AssertionError
----------------------------------------------------- Captured stderr call -----------------------------------------------------
127.0.0.1 - - [07/Mar/2016 13:39:07] "POST /post HTTP/1.1" 200 389
============================================== 1 failed, 1 passed in 1.94 seconds ==============================================

requests.exceptions.ConnectionError: [Errno 32] Broken pipe:

$ py.test test.py
============================= test session starts =============================
platform darwin -- Python 3.5.1, pytest-2.9.0, py-1.4.31, pluggy-0.3.1
rootdir: /private/tmp, inifile:
plugins: cov-2.2.1, httpbin-0.2.3
collected 2 items

test.py .F

================================== FAILURES ===================================
__________________________ test_stream_local_httpbin __________________________

httpbin = <Server(<class 'pytest_httpbin.serve.Server'>, started 123145309245440)>

    def test_stream_local_httpbin(httpbin):
>       r = requests.post(httpbin.url + '/post', data=stream())

test.py:16:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/jakub/.virtualenvs/httpie/lib/python3.5/site-packages/requests/api.py:107: in post
    return request('post', url, data=data, json=json, **kwargs)
/Users/jakub/.virtualenvs/httpie/lib/python3.5/site-packages/requests/api.py:53: in request
    return session.request(method=method, url=url, **kwargs)
/Users/jakub/.virtualenvs/httpie/lib/python3.5/site-packages/requests/sessions.py:468: in request
    resp = self.send(prep, **send_kwargs)
/Users/jakub/.virtualenvs/httpie/lib/python3.5/site-packages/requests/sessions.py:576: in send
    r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103501eb8>
request = <PreparedRequest [POST]>, stream = False
timeout = <requests.packages.urllib3.util.timeout.Timeout object at 0x103521860>
verify = True, cert = None, proxies = OrderedDict()

    def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None):
        """Sends PreparedRequest object. Returns Response object.

            :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
            :param stream: (optional) Whether to stream the request content.
            :param timeout: (optional) How long to wait for the server to send
                data before giving up, as a float, or a :ref:`(connect timeout,
                read timeout) <timeouts>` tuple.
            :type timeout: float or tuple
            :param verify: (optional) Whether to verify SSL certificates.
            :param cert: (optional) Any user-provided SSL certificate to be trusted.
            :param proxies: (optional) The proxies dictionary to apply to the request.
            """

        conn = self.get_connection(request.url, proxies)

        self.cert_verify(conn, request.url, verify, cert)
        url = self.request_url(request, proxies)
        self.add_headers(request)

        chunked = not (request.body is None or 'Content-Length' in request.headers)

        if isinstance(timeout, tuple):
            try:
                connect, read = timeout
                timeout = TimeoutSauce(connect=connect, read=read)
            except ValueError as e:
                # this may raise a string formatting error.
                err = ("Invalid timeout {0}. Pass a (connect, read) "
                       "timeout tuple, or a single float to set "
                       "both timeouts to the same value".format(timeout))
                raise ValueError(err)
        else:
            timeout = TimeoutSauce(connect=timeout, read=timeout)

        try:
            if not chunked:
                resp = conn.urlopen(
                    method=request.method,
                    url=url,
                    body=request.body,
                    headers=request.headers,
                    redirect=False,
                    assert_same_host=False,
                    preload_content=False,
                    decode_content=False,
                    retries=self.max_retries,
                    timeout=timeout
                )

            # Send the request.
            else:
                if hasattr(conn, 'proxy_pool'):
                    conn = conn.proxy_pool

                low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)

                try:
                    low_conn.putrequest(request.method,
                                        url,
                                        skip_accept_encoding=True)

                    for header, value in request.headers.items():
                        low_conn.putheader(header, value)

                    low_conn.endheaders()

                    for i in request.body:
                        low_conn.send(hex(len(i))[2:].encode('utf-8'))
                        low_conn.send(b'\r\n')
                        low_conn.send(i)
                        low_conn.send(b'\r\n')
                    low_conn.send(b'0\r\n\r\n')

                    # Receive the response from the server
                    try:
                        # For Python 2.7+ versions, use buffering of HTTP
                        # responses
                        r = low_conn.getresponse(buffering=True)
                    except TypeError:
                        # For compatibility with Python 2.6 versions and back
                        r = low_conn.getresponse()

                    resp = HTTPResponse.from_httplib(
                        r,
                        pool=conn,
                        connection=low_conn,
                        preload_content=False,
                        decode_content=False
                    )
                except Exception as e:
                    # If we hit any problems here, clean up the connection.
                    # Then, reraise so that we can handle the actual exception.
                    low_conn.close()
                    raise

        except (ProtocolError, socket.error) as err:
>           raise ConnectionError(err, request=request)
E           requests.exceptions.ConnectionError: [Errno 32] Broken pipe

/Users/jakub/.virtualenvs/httpie/lib/python3.5/site-packages/requests/adapters.py:426: ConnectionError
---------------------------- Captured stderr call -----------------------------
127.0.0.1 - - [07/Mar/2016 13:36:28] "POST /post HTTP/1.1" 200 389
===================== 1 failed, 1 passed in 2.10 seconds ======================

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions