-
Notifications
You must be signed in to change notification settings - Fork 258
/
httplib_chunk.py
123 lines (102 loc) · 3.62 KB
/
httplib_chunk.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""
Modified from standard httplib
1. HTTPConnection can send trunked data.
2. Remove httplib's automatic Content-Length insertion when data is a file-like object.
"""
# -*- coding: utf-8 -*-
import httplib
from httplib import _CS_REQ_STARTED, _CS_REQ_SENT
import string
import os
from array import array
class HTTPConnection(httplib.HTTPConnection):
def send(self, data, is_chunked=False):
"""Send `data' to the server."""
if self.sock is None:
if self.auto_open:
self.connect()
else:
raise NotConnected()
if self.debuglevel > 0:
print "send:", repr(data)
blocksize = 8192
if hasattr(data,'read') and not isinstance(data, array):
if self.debuglevel > 0: print "sendIng a read()able"
datablock = data.read(blocksize)
while datablock:
if self.debuglevel > 0:
print 'chunked:', is_chunked
if is_chunked:
if self.debuglevel > 0: print 'send: with trunked data'
lenstr = string.upper(hex(len(datablock))[2:])
self.sock.sendall('%s\r\n%s\r\n' % (lenstr, datablock))
else:
self.sock.sendall(datablock)
datablock = data.read(blocksize)
if is_chunked:
self.sock.sendall('0\r\n\r\n')
else:
self.sock.sendall(data)
def _set_content_length(self, body):
# Set the content-length based on the body.
thelen = None
try:
thelen = str(len(body))
except (TypeError, AttributeError), te:
# Don't send a length if this failed
if self.debuglevel > 0: print "Cannot stat!!"
if thelen is not None:
self.putheader('Content-Length', thelen)
return True
return False
def _send_request(self, method, url, body, headers):
# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
skips['skip_host'] = 1
if 'accept-encoding' in header_names:
skips['skip_accept_encoding'] = 1
self.putrequest(method, url, **skips)
is_chunked = False
if body and header_names.get('Transfer-Encoding') == 'chunked':
is_chunked = True
elif body and ('content-length' not in header_names):
is_chunked = not self._set_content_length(body)
if is_chunked:
self.putheader('Transfer-Encoding', 'chunked')
for hdr, value in headers.iteritems():
self.putheader(hdr, value)
self.endheaders(body, is_chunked=is_chunked)
def endheaders(self, message_body=None, is_chunked=False):
"""Indicate that the last header line has been sent to the server.
This method sends the request to the server. The optional
message_body argument can be used to pass a message body
associated with the request. The message body will be sent in
the same packet as the message headers if it is string, otherwise it is
sent as a separate packet.
"""
if self.__state == _CS_REQ_STARTED:
self.__state = _CS_REQ_SENT
else:
raise CannotSendHeader()
self._send_output(message_body, is_chunked=is_chunked)
def _send_output(self, message_body=None, is_chunked=False):
"""Send the currently buffered request and clear the buffer.
Appends an extra \\r\\n to the buffer.
A message_body may be specified, to be appended to the request.
"""
self._buffer.extend(("", ""))
msg = "\r\n".join(self._buffer)
del self._buffer[:]
# If msg and message_body are sent in a single send() call,
# it will avoid performance problems caused by the interaction
# between delayed ack and the Nagle algorithm.
if isinstance(message_body, str):
msg += message_body
message_body = None
self.send(msg)
if message_body is not None:
#message_body was not a string (i.e. it is a file) and
#we must run the risk of Nagle
self.send(message_body, is_chunked=is_chunked)