From 2246a52a364b794f38daf073b085d7d669446e73 Mon Sep 17 00:00:00 2001 From: tzickel Date: Fri, 8 Apr 2016 20:25:01 +0300 Subject: [PATCH 1/3] Added a test to show a faulty behaviour when posting binary data for an object with no __iter__ --- tests/test_requests.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index 282a6679..b5cf573e 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -482,6 +482,51 @@ class TestRequests: with pytest.raises(ValueError): requests.post(url, files=['bad file data']) + def test_POSTBIN_SEEKED_OBJECT_WITH_NO_ITER(self, httpbin): + + class BufferedStream(object): + def __init__(self, data): + if isinstance(data, buffer): + self.data = data + else: + self.data = buffer(data) + self.length = len(self.data) + self.index = 0 + + def __len__(self): + return self.length + + def read(self, size=None): + if size: + ret = buffer(self.data, self.index, size) + self.index += size + else: + ret = buffer(self.data, self.index) + self.index = self.length + return ret + + def tell(self): + return self.index + + def seek(self, offset, where=0): + if where == 0: + self.index = offset + elif where == 1: + self.index += offset + elif where == 2: + self.index = self.length + offset + + test = BufferedStream('test') + post1 = requests.post(httpbin('post'), data=test) + assert post1.status_code == 200 + assert post1.json()['data'] == 'test' + + test = BufferedStream('test') + test.seek(2) + post2 = requests.post(httpbin('post'), data=test) + assert post2.status_code == 200 + assert post2.json()['data'] == 'st' + def test_POSTBIN_GET_POST_FILES_WITH_DATA(self, httpbin): url = httpbin('post') From fb230709a8d35d8d2973eab3365cb8f9664cfa90 Mon Sep 17 00:00:00 2001 From: tzickel Date: Fri, 8 Apr 2016 22:23:35 +0300 Subject: [PATCH 2/3] Fix for the test ? --- requests/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/requests/models.py b/requests/models.py index 54428882..fe4bec1b 100644 --- a/requests/models.py +++ b/requests/models.py @@ -465,9 +465,11 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): def prepare_content_length(self, body): if hasattr(body, 'seek') and hasattr(body, 'tell'): + curr_pos = body.tell() body.seek(0, 2) - self.headers['Content-Length'] = builtin_str(body.tell()) - body.seek(0, 0) + end_pos = body.tell() + self.headers['Content-Length'] = builtin_str(max(0, end_pos - curr_pos)) + body.seek(curr_pos, 0) elif body is not None: l = super_len(body) if l: From 219490ea7fe0907bb12222e913cb4d1a63483e3c Mon Sep 17 00:00:00 2001 From: tzickel Date: Fri, 8 Apr 2016 23:17:37 +0300 Subject: [PATCH 3/3] Make a dummy test --- tests/test_requests.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index b5cf573e..04a27a44 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -484,12 +484,9 @@ class TestRequests: def test_POSTBIN_SEEKED_OBJECT_WITH_NO_ITER(self, httpbin): - class BufferedStream(object): + class TestStream(object): def __init__(self, data): - if isinstance(data, buffer): - self.data = data - else: - self.data = buffer(data) + self.data = data.encode() self.length = len(self.data) self.index = 0 @@ -498,10 +495,10 @@ class TestRequests: def read(self, size=None): if size: - ret = buffer(self.data, self.index, size) + ret = self.data[self.index:self.index + size] self.index += size else: - ret = buffer(self.data, self.index) + ret = self.data[self.index:] self.index = self.length return ret @@ -516,12 +513,12 @@ class TestRequests: elif where == 2: self.index = self.length + offset - test = BufferedStream('test') + test = TestStream('test') post1 = requests.post(httpbin('post'), data=test) assert post1.status_code == 200 assert post1.json()['data'] == 'test' - test = BufferedStream('test') + test = TestStream('test') test.seek(2) post2 = requests.post(httpbin('post'), data=test) assert post2.status_code == 200