Fixed parser not setting stream on Django request

This commit is contained in:
steven 2013-09-11 12:59:11 +07:00
parent e021472a16
commit 8b724c994d

View File

@ -8,6 +8,7 @@ from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.files.uploadhandler import StopFutureHandlers from django.core.files.uploadhandler import StopFutureHandlers
from django.http import QueryDict from django.http import QueryDict
from django.http.request import HttpRequest
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
from rest_framework.compat import etree, six, yaml from rest_framework.compat import etree, six, yaml
@ -32,6 +33,16 @@ class BaseParser(object):
media_type = None media_type = None
def prepare_stream(self, stream):
"""
Given a stream to read from, prepare the stream before parsed.
In case of django ``HttpRequest`` object, let it assign correct variable
from stream before consuming it.
"""
if isinstance(stream, HttpRequest):
stream.body
return stream
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Given a stream to read from, return the parsed representation. Given a stream to read from, return the parsed representation.
@ -57,6 +68,7 @@ class JSONParser(BaseParser):
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
try: try:
stream = self.prepare_stream(stream)
data = stream.read().decode(encoding) data = stream.read().decode(encoding)
return json.loads(data) return json.loads(data)
except ValueError as exc: except ValueError as exc:
@ -80,6 +92,7 @@ class YAMLParser(BaseParser):
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
try: try:
stream = self.prepare_stream(stream)
data = stream.read().decode(encoding) data = stream.read().decode(encoding)
return yaml.safe_load(data) return yaml.safe_load(data)
except (ValueError, yaml.parser.ParserError) as exc: except (ValueError, yaml.parser.ParserError) as exc:
@ -100,6 +113,7 @@ class FormParser(BaseParser):
""" """
parser_context = parser_context or {} parser_context = parser_context or {}
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
stream = self.prepare_stream(stream)
data = QueryDict(stream.read(), encoding=encoding) data = QueryDict(stream.read(), encoding=encoding)
return data return data
@ -127,6 +141,7 @@ class MultiPartParser(BaseParser):
upload_handlers = request.upload_handlers upload_handlers = request.upload_handlers
try: try:
stream = self.prepare_stream(stream)
parser = DjangoMultiPartParser(meta, stream, upload_handlers, encoding) parser = DjangoMultiPartParser(meta, stream, upload_handlers, encoding)
data, files = parser.parse() data, files = parser.parse()
return DataAndFiles(data, files) return DataAndFiles(data, files)
@ -151,6 +166,7 @@ class XMLParser(BaseParser):
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
parser = etree.DefusedXMLParser(encoding=encoding) parser = etree.DefusedXMLParser(encoding=encoding)
try: try:
stream = self.prepare_stream(stream)
tree = etree.parse(stream, parser=parser, forbid_dtd=True) tree = etree.parse(stream, parser=parser, forbid_dtd=True)
except (etree.ParseError, ValueError) as exc: except (etree.ParseError, ValueError) as exc:
raise ParseError('XML parse error - %s' % six.u(exc)) raise ParseError('XML parse error - %s' % six.u(exc))