diff options
Diffstat (limited to 'djangorestframework/request.py')
| -rw-r--r-- | djangorestframework/request.py | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/djangorestframework/request.py b/djangorestframework/request.py deleted file mode 100644 index 450d2ac7..00000000 --- a/djangorestframework/request.py +++ /dev/null @@ -1,284 +0,0 @@ -""" -The :mod:`request` module provides a :class:`Request` class used to wrap the standard `request` -object received in all the views. - -The wrapped request then offers a richer API, in particular : - - - content automatically parsed according to `Content-Type` header, - and available as :meth:`.DATA<Request.DATA>` - - full support of PUT method, including support for file uploads - - form overloading of HTTP method, content type and content -""" -from StringIO import StringIO - -from djangorestframework import exceptions -from djangorestframework.settings import api_settings -from djangorestframework.utils.mediatypes import is_form_media_type - - -__all__ = ('Request',) - - -class Empty(object): - """ - Placeholder for unset attributes. - Cannot use `None`, as that may be a valid value. - """ - pass - - -def _hasattr(obj, name): - return not getattr(obj, name) is Empty - - -class Request(object): - """ - Wrapper allowing to enhance a standard `HttpRequest` instance. - - Kwargs: - - request(HttpRequest). The original request instance. - - parsers_classes(list/tuple). The parsers to use for parsing the - request content. - - authentication_classes(list/tuple). The authentications used to try - authenticating the request's user. - """ - - _METHOD_PARAM = api_settings.FORM_METHOD_OVERRIDE - _CONTENT_PARAM = api_settings.FORM_CONTENT_OVERRIDE - _CONTENTTYPE_PARAM = api_settings.FORM_CONTENTTYPE_OVERRIDE - - def __init__(self, request, parser_classes=None, authentication_classes=None): - self._request = request - self.parser_classes = parser_classes or () - self.authentication_classes = authentication_classes or () - self._data = Empty - self._files = Empty - self._method = Empty - self._content_type = Empty - self._stream = Empty - - def get_parsers(self): - """ - Instantiates and returns the list of parsers the request will use. - """ - return [parser() for parser in self.parser_classes] - - def get_authentications(self): - """ - Instantiates and returns the list of parsers the request will use. - """ - return [authentication() for authentication in self.authentication_classes] - - @property - def method(self): - """ - Returns the HTTP method. - - This allows the `method` to be overridden by using a hidden `form` - field on a form POST request. - """ - if not _hasattr(self, '_method'): - self._load_method_and_content_type() - return self._method - - @property - def content_type(self): - """ - Returns the content type header. - - This should be used instead of ``request.META.get('HTTP_CONTENT_TYPE')``, - as it allows the content type to be overridden by using a hidden form - field on a form POST request. - """ - if not _hasattr(self, '_content_type'): - self._load_method_and_content_type() - return self._content_type - - @property - def stream(self): - """ - Returns an object that may be used to stream the request content. - """ - if not _hasattr(self, '_stream'): - self._load_stream() - return self._stream - - @property - def DATA(self): - """ - Parses the request body and returns the data. - - Similar to usual behaviour of `request.POST`, except that it handles - arbitrary parsers, and also works on methods other than POST (eg PUT). - """ - if not _hasattr(self, '_data'): - self._load_data_and_files() - return self._data - - @property - def FILES(self): - """ - Parses the request body and returns any files uploaded in the request. - - Similar to usual behaviour of `request.FILES`, except that it handles - arbitrary parsers, and also works on methods other than POST (eg PUT). - """ - if not _hasattr(self, '_files'): - self._load_data_and_files() - return self._files - - @property - def user(self): - """ - Returns the user associated with the current request, as authenticated - by the authentication classes provided to the request. - """ - if not hasattr(self, '_user'): - self._user, self._auth = self._authenticate() - return self._user - - @property - def auth(self): - """ - Returns any non-user authentication information associated with the - request, such as an authentication token. - """ - if not hasattr(self, '_auth'): - self._user, self._auth = self._authenticate() - return self._auth - - def _load_data_and_files(self): - """ - Parses the request content into self.DATA and self.FILES. - """ - if not _hasattr(self, '_content_type'): - self._load_method_and_content_type() - - if not _hasattr(self, '_data'): - self._data, self._files = self._parse() - - def _load_method_and_content_type(self): - """ - Sets the method and content_type, and then check if they've - been overridden. - """ - self._content_type = self.META.get('HTTP_CONTENT_TYPE', - self.META.get('CONTENT_TYPE', '')) - self._perform_form_overloading() - # if the HTTP method was not overloaded, we take the raw HTTP method - if not _hasattr(self, '_method'): - self._method = self._request.method - - def _load_stream(self): - """ - Return the content body of the request, as a stream. - """ - try: - content_length = int(self.META.get('CONTENT_LENGTH', - self.META.get('HTTP_CONTENT_LENGTH'))) - except (ValueError, TypeError): - content_length = 0 - - if content_length == 0: - self._stream = None - elif hasattr(self._request, 'read'): - self._stream = self._request - else: - self._stream = StringIO(self.raw_post_data) - - def _perform_form_overloading(self): - """ - If this is a form POST request, then we need to check if the method and - content/content_type have been overridden by setting them in hidden - form fields or not. - """ - - USE_FORM_OVERLOADING = ( - self._METHOD_PARAM or - (self._CONTENT_PARAM and self._CONTENTTYPE_PARAM) - ) - - # We only need to use form overloading on form POST requests. - if (not USE_FORM_OVERLOADING - or self._request.method != 'POST' - or not is_form_media_type(self._content_type)): - return - - # At this point we're committed to parsing the request as form data. - self._data = self._request.POST - self._files = self._request.FILES - - # Method overloading - change the method and remove the param from the content. - if (self._METHOD_PARAM and - self._METHOD_PARAM in self._data): - self._method = self._data[self._METHOD_PARAM].upper() - self._data.pop(self._METHOD_PARAM) - - # Content overloading - modify the content type, and re-parse. - if (self._CONTENT_PARAM and - self._CONTENTTYPE_PARAM and - self._CONTENT_PARAM in self._data and - self._CONTENTTYPE_PARAM in self._data): - self._content_type = self._data[self._CONTENTTYPE_PARAM] - self._stream = StringIO(self._data[self._CONTENT_PARAM]) - self._data.pop(self._CONTENTTYPE_PARAM) - self._data.pop(self._CONTENT_PARAM) - self._data, self._files = self._parse() - - def _parse(self): - """ - Parse the request content, returning a two-tuple of (data, files) - - May raise an `UnsupportedMediaType`, or `ParseError` exception. - """ - if self.stream is None or self.content_type is None: - return (None, None) - - for parser in self.get_parsers(): - if parser.can_handle_request(self.content_type): - parsed = parser.parse(self.stream, meta=self.META, - upload_handlers=self.upload_handlers) - # Parser classes may return the raw data, or a - # DataAndFiles object. Unpack the result as required. - try: - return (parsed.data, parsed.files) - except AttributeError: - return (parsed, None) - - raise exceptions.UnsupportedMediaType(self._content_type) - - def _authenticate(self): - """ - Attempt to authenticate the request using each authentication instance in turn. - Returns a two-tuple of (user, authtoken). - """ - for authentication in self.get_authentications(): - user_auth_tuple = authentication.authenticate(self) - if not user_auth_tuple is None: - return user_auth_tuple - return self._not_authenticated() - - def _not_authenticated(self): - """ - Return a two-tuple of (user, authtoken), representing an - unauthenticated request. - - By default this will be (AnonymousUser, None). - """ - if api_settings.UNAUTHENTICATED_USER: - user = api_settings.UNAUTHENTICATED_USER() - else: - user = None - - if api_settings.UNAUTHENTICATED_TOKEN: - auth = api_settings.UNAUTHENTICATED_TOKEN() - else: - auth = None - - return (user, auth) - - def __getattr__(self, attr): - """ - Proxy other attributes to the underlying HttpRequest object. - """ - return getattr(self._request, attr) |
