a3cb3f00560926d57adb82613fb61a33e31f741b
1 # -*- coding: utf-8 -*-
3 import itertools
, mimetools
, mimetypes
5 from txclib
import get_version
7 # Helper class to enable urllib2 to handle PUT/DELETE requests as well
8 class RequestWithMethod(urllib2
.Request
):
9 """Workaround for using DELETE with urllib2"""
10 def __init__(self
, url
, method
, data
=None, headers
={},
11 origin_req_host
=None, unverifiable
=False):
13 urllib2
.Request
.__init__(self
, url
, data
=data
, headers
=headers
,
14 origin_req_host
=None, unverifiable
=False)
21 from cStringIO
import StringIO
24 def __init__(self
, anycallable
):
25 self
.__call__
= anycallable
27 # Controls how sequences are uncoded. If true, elements may be given multiple
28 # values by assigning a sequence.
31 class MultipartPostHandler(urllib2
.BaseHandler
):
32 handler_order
= urllib2
.HTTPHandler
.handler_order
- 10 # needs to run first
34 def http_request(self
, request
):
35 data
= request
.get_data()
36 if data
is not None and type(data
) != str:
40 for(key
, value
) in data
.items():
41 if type(value
) == file:
42 v_files
.append((key
, value
))
44 v_vars
.append((key
, value
))
46 systype
, value
, traceback
= sys
.exc_info()
47 raise TypeError, "not a valid non-string sequence or mapping object", traceback
50 data
= urllib
.urlencode(v_vars
, doseq
)
52 boundary
, data
= self
.multipart_encode(v_vars
, v_files
)
54 contenttype
= 'multipart/form-data; boundary=%s' % boundary
55 if(request
.has_header('Content-Type')
56 and request
.get_header('Content-Type').find('multipart/form-data') != 0):
57 print "Replacing %s with %s" %
(request
.get_header('content-type'), 'multipart/form-data')
58 request
.add_unredirected_header('Content-Type', contenttype
)
60 request
.add_data(data
)
64 def multipart_encode(vars, files
, boundary
= None, buf
= None):
66 boundary
= mimetools
.choose_boundary()
69 for(key
, value
) in vars:
70 buf
.write('--%s\r\n' % boundary
)
71 buf
.write('Content-Disposition: form-data; name="%s"' % key
)
72 buf
.write('\r\n\r\n' + value
+ '\r\n')
73 for(key
, fd
) in files
:
74 file_size
= os
.fstat(fd
.fileno())[stat
.ST_SIZE
]
75 filename
= fd
.name
.split('/')[-1]
76 contenttype
= mimetypes
.guess_type(filename
)[0] or 'application/octet-stream'
77 buf
.write('--%s\r\n' % boundary
)
78 buf
.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' %
(key
, filename
))
79 buf
.write('Content-Type: %s\r\n' % contenttype
)
80 # buffer += 'Content-Length: %s\r\n' % file_size
82 buf
.write('\r\n' + fd
.read() + '\r\n')
83 buf
.write('--' + boundary
+ '--\r\n\r\n')
86 multipart_encode
= Callable(multipart_encode
)
88 https_request
= http_request
91 def user_agent_identifier():
92 """Return the user agent for the client."""
93 client_info
= (get_version(), platform
.system(), platform
.machine())
94 return "txclient/%s (%s %s)" % client_info