Skip to content

Commit ea6191a

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 d6dea8e commit ea6191a

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

agithub/base.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,14 @@ def get(self, url, headers={}, **params):
153153
def post(self, url, body=None, headers={}, **params):
154154
url += self.urlencode(params)
155155
if not 'content-type' in headers:
156-
# We're doing a json.dumps of body, so let's set the content-type to json
157156
headers['content-type'] = 'application/json'
158-
return self.request('POST', url, json.dumps(body), headers)
157+
return self.request('POST', url, body, headers)
159158

160159
def put(self, url, body=None, headers={}, **params):
161160
url += self.urlencode(params)
162161
if not 'content-type' in headers:
163-
# We're doing a json.dumps of body, so let's set the content-type to json
164162
headers['content-type'] = 'application/json'
165-
return self.request('PUT', url, json.dumps(body), headers)
163+
return self.request('PUT', url, body, headers)
166164

167165
def delete(self, url, headers={}, **params):
168166
url += self.urlencode(params)
@@ -175,19 +173,19 @@ def patch(self, url, body=None, headers={}, **params):
175173
"""
176174
url += self.urlencode(params)
177175
if not 'content-type' in headers:
178-
# We're doing a json.dumps of body, so let's set the content-type to json
179176
headers['content-type'] = 'application/json'
180-
return self.request('PATCH', url, json.dumps(body), headers)
177+
return self.request('PATCH', url, body, headers)
181178

182-
def request(self, method, url, body, headers):
179+
def request(self, method, url, bodyData, headers):
183180
'''Low-level networking. All HTTP-method methods call this'''
184181

185182
headers = self._fix_headers(headers)
186183
url = self.prop.constructUrl(url)
187184

188185
#TODO: Context manager
186+
requestBody = RequestBody(bodyData, headers)
189187
conn = self.get_connection()
190-
conn.request(method, url, body, headers)
188+
conn.request(method, url, requestBody.process(), headers)
191189
response = conn.getresponse()
192190
status = response.status
193191
content = ResponseBody(response)
@@ -327,6 +325,56 @@ def application_json(self):
327325

328326
# Insert new media-type handlers here
329327

328+
class RequestBody(Body):
329+
'''
330+
Encode a request body from the client, respecting the Content-Type
331+
field
332+
'''
333+
def __init__(self, body, headers):
334+
self.body = body
335+
self.headers = headers
336+
self.parseContentType(
337+
getattr(self.headers, 'content-type', None))
338+
self.encoding = self.ctypeParameters['charset']
339+
340+
def encodeBody(self):
341+
'''
342+
Encode (and overwrite) self.body via the charset encoding
343+
specified in the request headers. This should be called by the
344+
media-type handler when appropriate
345+
'''
346+
self.body = self.body.encode(self.encoding)
347+
348+
def process(self):
349+
'''
350+
Process the request body by applying a media-type specific
351+
handler to it.
352+
'''
353+
if self.body is None:
354+
return None
355+
356+
handlerName = self.funMangledMediaType()
357+
handler = getattr( self, handlerName,
358+
self.application_octet_stream
359+
)
360+
return handler()
361+
362+
## media-type handlers
363+
364+
def application_octet_stream(self):
365+
'''Handler for binary data and unknown media-types. Importantly,
366+
it does absolutely no pre-processing of the body, which means it
367+
will not mess it up.
368+
'''
369+
return self.body
370+
371+
def application_json(self):
372+
self.body = json.dumps(self.body)
373+
self.encodeBody()
374+
return self.body
375+
376+
# Insert new Request media-type handlers here
377+
330378
class ConnectionProperties(object):
331379
__slots__ = ['api_url', 'url_prefix', 'secure_http', 'extra_headers']
332380

0 commit comments

Comments
 (0)