Skip to content

Commit f0f09ac

Browse files
committed
New class RequestBody: Content-Type encoding of the request body
Client: - The HTTP methods which accept a body now pass it unchanged to Client.request - Client.request now constructs a RequestBody, and uses it to process the user-supplied body RequestBody Handles charset encoding and media-type serialization; it is structured very similarly to ResponseBody
1 parent ff6c0e8 commit f0f09ac

File tree

1 file changed

+58
-5
lines changed

1 file changed

+58
-5
lines changed

agithub.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@ def get(self, url, headers={}, **params):
199199

200200
def post(self, url, body=None, headers={}, **params):
201201
url += self.urlEncode(params)
202-
return self.request('POST', url, json.dumps(body), headers)
202+
return self.request('POST', url, body, headers)
203203

204204
def put(self, url, body=None, headers={}, **params):
205205
url += self.urlEncode(params)
206-
return self.request('PUT', url, json.dumps(body), headers)
206+
return self.request('PUT', url, body, headers)
207207

208208
def delete(self, url, headers={}, **params):
209209
url += self.urlEncode(params)
@@ -215,7 +215,7 @@ def patch(self, url, body=None, headers={}, **params):
215215
Parameters is a dictionary that will will be url-encoded
216216
"""
217217
url += self.urlEncode(params)
218-
return self.request(self.PATCH, url, json.dumps(body), headers)
218+
return self.request(self.PATCH, url, body, headers)
219219

220220
def request(self, method, url, body, headers):
221221
'''Low-level networking. All HTTP-method methods call this'''
@@ -225,9 +225,9 @@ def request(self, method, url, body, headers):
225225
if self.username:
226226
headers['authorization'] = self.authHeader
227227

228-
#TODO: Context manager
228+
reqBody = RequestBody(body, headers)
229229
conn = self.getConnection()
230-
conn.request(method, url, body, headers)
230+
conn.request(method, url, reqBody.process(), headers)
231231
response = conn.getresponse()
232232
status = response.status
233233
resBody = ResponseBody(response)
@@ -383,6 +383,59 @@ def application_json(self):
383383

384384
# Insert new media-type handlers here
385385

386+
class RequestBody(Body):
387+
'''
388+
Encode a request body from the client, respecting the Content-Type
389+
field
390+
'''
391+
def __init__(self, body, headers):
392+
self.body = body
393+
self.headers = headers
394+
self.parseContentType(
395+
getattr(self.headers, 'content-type', None)
396+
)
397+
self.encoding = self.ctypeParameters['charset']
398+
399+
def encodeBody(self):
400+
'''
401+
Encode (and overwrite) self.body via the charset encoding
402+
specified in the request headers
403+
'''
404+
self.body = self.body.encode(self.encoding)
405+
406+
def process(self):
407+
'''
408+
Process the request body by applying a media-type specific
409+
handler to it. Some media-types need charset encoding as well,
410+
and it is up to the handler to do this by calling
411+
self.encodeBody()
412+
'''
413+
if self.body is None:
414+
return None
415+
416+
handlerName = self.funMangledMediaType()
417+
handler = getattr( self, handlerName,
418+
self.application_octet_stream
419+
)
420+
return handler()
421+
422+
## media-type handlers
423+
424+
def application_octet_stream(self):
425+
'''Handler for binary data and unknown media-types. Importantly,
426+
it does absolutely no pre-processing of the body, which means it
427+
will not mess it up.
428+
'''
429+
return self.body
430+
431+
def application_json(self):
432+
self.body = json.dumps(self.body)
433+
self.encodeBody()
434+
return self.body
435+
436+
# Insert new Request media-type handlers here
437+
438+
386439
class ConnectionProperties(object):
387440
__slots__ = ['api_url', 'secure_http', 'extra_headers']
388441

0 commit comments

Comments
 (0)