Beispiel #1
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ("POST", "PUT"):
            try:
                translate_mime(request)
            except MimerDataException, e:
                if e:
                    r = rc.BAD_REQUEST
                    r.content = e
                    return r
                return rc.BAD_REQUEST
            if not hasattr(request, "data"):
                if rm == "POST":
                    request.data = request.POST
                else:
                    request.data = request.PUT
Beispiel #2
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            except UnsupportedMediaTypeException:
                return rc.UNSUPPORTED_MEDIA_TYPE
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter through (?P<emitter_format>) and ?format=emitter
        # and lastly Accept: header processing
        em_format = self.determine_emitter(request, *args, **kwargs)
        if not em_format:
            request_has_accept = 'HTTP_ACCEPT' in request.META
            if request_has_accept and self.strict_accept:
                return rc.NOT_ACCEPTABLE
            em_format = self.default_emitter

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except Exception, e:
            result = self.error_handler(e, request, meth, em_format)
Beispiel #3
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        if not self.authentication.is_authenticated(request):
            if hasattr(self.handler, 'anonymous') and \
                callable(self.handler.anonymous) and \
                rm in self.handler.anonymous.allowed_methods:

                handler = self.handler.anonymous()
                anonymous = True
            else:
                return self.authentication.challenge()
        else:
            handler = self.handler
            anonymous = handler.is_anonymous
        
        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException, e:
                return rc.BAD_REQUEST
Beispiel #4
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        if not self.authentication.is_authenticated(request):
            if self.anonymous and \
                rm in self.anonymous.allowed_methods:

                handler = self.anonymous()
                anonymous = True
            else:
                return self.authentication.challenge()
        else:
            handler = self.handler
            anonymous = handler.is_anonymous
        
        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
      
        # Handle 'tunneling' alternate method over POST 
        if rm == "POST" and 'method' in request.POST:
            rm = request.POST['method'].upper()
        
        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)
        
        meth = getattr(handler, self.callmap.get(rm), None)
        
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)
        
        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)
        
        try:
            result = meth(request, *args, **kwargs)
        except FormValidationError, e:
            resp = rc.BAD_REQUEST
            resp.write(' '+str(e.form.errors))
            
            return resp
Beispiel #5
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Allow for emulated PUT requests -- http://backbonejs.org/#Sync-emulateHTTP
        if 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
            rm = request.META.get('HTTP_X_HTTP_METHOD_OVERRIDE')
            if rm == "PUT":
                request.PUT = request.POST

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except Exception, e:
            result = self.error_handler(e, request, meth, em_format)
Beispiel #6
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Allow for emulated PUT requests -- http://backbonejs.org/#Sync-emulateHTTP
        if 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
            rm = request.META.get('HTTP_X_HTTP_METHOD_OVERRIDE')
            if rm == "PUT":
                request.PUT = request.POST

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except Exception, e:
            result = self.error_handler(e, request, meth, em_format)
Beispiel #7
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        self._request = request

        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        if not self.authentication.is_authenticated(request):
            if hasattr(self.handler, 'anonymous') and \
                callable(self.handler.anonymous) and \
                rm in self.handler.anonymous.allowed_methods:

                handler = self.handler.anonymous()
                anonymous = True
            else:
                return self.authentication.challenge()
        else:
            handler = self.handler
            anonymous = handler.is_anonymous

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm), None)

        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except FormValidationError, e:
            # TODO: Use rc.BAD_REQUEST here
            return HttpResponse("Bad Request: %s" % e.form.errors, status=400)
Beispiel #8
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm), None)

        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except FormValidationError, e:
            resp = rc.BAD_REQUEST
            resp.write(' ' + str(e.form.errors))

            return resp
Beispiel #9
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter through (?P<emitter_format>) and ?format=emitter
        # and lastly Accept: header processing
        em_format = self.determine_emitter(request, *args, **kwargs)
        if not em_format:
            request_has_accept = 'HTTP_ACCEPT' in request.META
            if request_has_accept and self.strict_accept:
                return rc.NOT_ACCEPTABLE
            em_format = self.default_emitter

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except Exception as e:
            result = self.error_handler(e, request, meth, em_format)

        try:
            emitter, ct = Emitter.get(em_format)
            fields = handler.fields

            if hasattr(handler, 'list_fields') and isinstance(
                    result, (list, tuple, QuerySet)):
                fields = handler.list_fields
        except ValueError:
            result = rc.BAD_REQUEST
            result.content = "Invalid output format specified '%s'." % em_format
            return result

        status_code = 200

        # If we're looking at a response object which contains non-string
        # content, then assume we should use the emitter to format that
        # content
        if self._use_emitter(result):
            status_code = result.status_code
            # Note: We can't use result.content here because that
            # method attempts to convert the content into a string
            # which we don't want.  when
            # _is_string/_base_content_is_iter is False _container is
            # the raw data
            result = result._container

        srl = emitter(result, typemapper, handler, fields, anonymous)

        try:
            """
            Decide whether or not we want a generator here,
            or we just want to buffer up the entire result
            before sending it to the client. Won't matter for
            smaller datasets, but larger will have an impact.
            """
            if self.stream: stream = srl.stream_render(request)
            else: stream = srl.render(request)

            if not isinstance(stream, HttpResponse):
                resp = HttpResponse(stream,
                                    content_type=ct,
                                    status=status_code)
            else:
                resp = stream

            resp.streaming = self.stream

            return resp
        except HttpStatusCode as e:
            return e.response
Beispiel #10
0
    def handle(self, request,*args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        if not self.authentication.is_authenticated(request):
            if hasattr(self.handler, 'anonymous') and \
                callable(self.handler.anonymous) and \
                rm in self.handler.anonymous.allowed_methods:

                handler = self.handler.anonymous()
                anonymous = True
            else:
                return self.authentication.challenge()
        else:
            handler = self.handler
            anonymous = handler.is_anonymous
        
        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
        
        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)
        
        meth = getattr(handler, self.callmap.get(rm), None)
                
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)
        kwargs.pop('emitter_format', None)

        # result is just html, handled in template
        # TODO: move this block into sites.py view handler
        if em_format == 'html':
            temp = get_template('fulcrum/resource_detail.html')
            ctxt = RequestContext(request, { 'resource': self, 'handler': self.handler })
            return HttpResponse(temp.render(ctxt))
        
        # Get recursion level
        recurse_level = self.get_recurse_level(request)
        
        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)
                
        try:
            # result is either a single object or a list of objects
            # something like... [<Blogpost: Sample test post 2>]
            result = meth(request, *args, **kwargs)
        except FormValidationError, e:
            # TODO: Use rc.BAD_REQUEST here
            return HttpResponse("Bad Request: %s" % e.form.errors, status=400)
Beispiel #11
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        if not self.authentication.is_authenticated(request):
            if self.anonymous and \
                rm in self.anonymous.allowed_methods:

                handler = self.anonymous()
                anonymous = True
            else:
                return self.authentication.challenge()
        else:
            handler = self.handler
            anonymous = handler.is_anonymous
        
        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
        
        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)
        
        meth = getattr(handler, self.callmap.get(rm), None)
        
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)
        
        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        def call_piston_precondition(meth, *args, **kwargs):
            if hasattr(meth, 'piston_precondition_decorator'):
                @meth.piston_precondition_decorator
                def fake_controller(request, *args, **kwargs):
                    return rc.ALL_OK
                return fake_controller(request, *args, **kwargs)
            return rc.ALL_OK

        etag=None
        response = call_piston_precondition(meth, *args, **kwargs)
        if response.status_code != 200:
            return response
            
        try:
            result = meth(request, *args, **kwargs)

            # get new etag - it might have been changed
            tmp_r = call_piston_precondition(meth, *args, **kwargs)
            if tmp_r.has_header('ETag'):
                etag = tmp_r['ETag']
            
        except FormValidationError, e:
            resp = rc.BAD_REQUEST
            resp.write(' '+str(e.form.errors))
            
            return resp
Beispiel #12
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        if rm == 'POST':
            block = getattr(request, 'POST', { })

            # Support alternative request types via
            # _method parameter in POST requests
            if '_method' in block:
                rm = request.method = block['_method'].upper()
                sanitized = block.copy()
                sanitized.pop('_method')
                setattr(request, 'POST', sanitized)

                if rm == 'PUT':
                    request.PUT = request.POST

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        elif rm == 'PUT':
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor()
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        try:
            result = meth(request, *args, **kwargs)
        except Exception, e:
            result = self.error_handler(e, request, meth, em_format)
Beispiel #13
0
    def __call__(self, request, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # PUT request, so we trick it a little here.
        if rm == "PUT":
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        if anonymous is CHALLENGE:
            return actor(request)
        else:
            handler = actor

        # Translate nested datastructs into `request.data` here.
        if rm in ('POST', 'PUT'):
            try:
                translate_mime(request)
            except MimerDataException:
                return rc.BAD_REQUEST
            if not hasattr(request, 'data'):
                if rm == 'POST':
                    request.data = request.POST
                else:
                    request.data = request.PUT

        if not rm in handler.allowed_methods:
            return HttpResponseNotAllowed(handler.allowed_methods)

        meth = getattr(handler, self.callmap.get(rm, ''), None)
        if not meth:
            raise Http404

        # Support emitter both through (?P<emitter_format>) and ?format=emitter.
        em_format = self.determine_emitter(request, *args, **kwargs)

        kwargs.pop('emitter_format', None)

        # Clean up the request object a bit, since we might
        # very well have `oauth_`-headers in there, and we
        # don't want to pass these along to the handler.
        request = self.cleanup_request(request)

        result = meth(request, *args, **kwargs)

        try:
            emitter, ct = Emitter.get(em_format)
            fields = handler.fields

            if hasattr(handler, 'list_fields') and isinstance(result, (list, tuple, QuerySet)):
                fields = handler.list_fields
        except ValueError:
            result = rc.BAD_REQUEST
            result.content = "Invalid output format specified '%s'." % em_format
            return result

        status_code = 200

        # If we're looking at a response object which contains non-string
        # content, then assume we should use the emitter to format that
        # content
        if isinstance(result, HttpResponse) and not result._is_string:
            status_code = result.status_code
            # Note: We can't use result.content here because that method attempts
            # to convert the content into a string which we don't want.
            # when _is_string is False _container is the raw data
            result = result._container

        srl = emitter(result, typemapper, handler, fields, anonymous)

        try:
            """
            Decide whether or not we want a generator here,
            or we just want to buffer up the entire result
            before sending it to the client. Won't matter for
            smaller datasets, but larger will have an impact.
            """
            if self.stream: stream = srl.stream_render(request)
            else: stream = srl.render(request)

            if not isinstance(stream, HttpResponse):
                resp = HttpResponse(stream, mimetype=ct, status=status_code)
            else:
                resp = stream

            resp.streaming = self.stream

            return resp
        except HttpStatusCode, e:
            return e.response
Beispiel #14
0
    def process_request(self, request, response, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # on non POST request, so we trick it a little here.
        if rm in (
                "PUT",
                "DELETE",
        ):
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        result = None
        if anonymous is CHALLENGE:

            class ErrorHandler(BaseHandler):
                def error(self, *args, **kwargs):
                    pass

            for func in self.callmap.values():
                setattr(ErrorHandler, func, ErrorHandler.error)

            handler = ErrorHandler()
            meth = handler.error
            fields = ()
            response.data = actor(request)
        else:
            handler = actor
            meth = None
            fields = ()

        if not response.data:
            # Translate nested datastructs into `request.data` here.
            if rm in (
                    'POST',
                    'PUT',
                    'DELETE',
            ):
                try:
                    translate_mime(request)
                except MimerDataException:
                    raise PistonBadRequestException(
                        'Error deserializing request data.')
                if not hasattr(request, 'data'):
                    if rm == 'POST':
                        request.data = request.POST
                    elif rm == 'PUT':
                        request.data = request.PUT
                    elif rm == 'DELETE':
                        request.data = request.DELETE

                if not request.data:
                    # In the case where no data is provided, default to an empty
                    # dictionary. Many serializers do not deal with empty string data
                    # for deserialization.
                    setattr(request, rm, {})
                    request.data = {}

            if not rm in handler.allowed_methods:
                raise PistonMethodException(
                    headers={'Allow': handler.allowed_methods})

            meth = getattr(handler, self.callmap.get(rm, ''), None)
            if not meth:
                raise PistonNotFoundException

            # Clean up the request object a bit, since we might
            # very well have `oauth_`-headers in there, and we
            # don't want to pass these along to the handler.
            request = self.cleanup_request(request)

            response.data = meth(request, *args, **kwargs)

            fields = handler.fields

            if hasattr(handler, 'list_fields') and isinstance(
                    response.data, (list, tuple, QuerySet)):
                fields = handler.list_fields

        return handler, meth, fields, anonymous
Beispiel #15
0
    def cleanup(self, request, *args, **kwargs):
        """
        Cleanes up the incoming request, makes sure it's valid and allowed. In
        detail, the checks performed are the folowing:
        
        * If the request is I{PUT}, transform its data to I{POST}.
        * If request is I{PUT} or I{POST}, make sure the request body
          conforms to the I{Content-Type} header.
        * If request is I{PUT} with a list in the request body, raise
          exception. If request is I{Bulk-POST} and ``bulk_create`` has not
          been set, raise exception.
        * Makes sure that non-allowed incoming fields, are cut off the request
          body.
        """
        request_method = request.method.upper()
         
        # Construct the request.data dictionary, if the request is PUT/POST
        if request_method in ('PUT', 'POST'):
            if request_method == 'PUT':
                # TODO: STUDY what this does exactly
                coerce_put_post(request)
            # Check whether data has the correct format, according to
            # ``Content-Type``          
            if request_method in ('PUT', 'POST'):
                try:
                    translate_mime(request)
                except ValidationError:
                    raise
                if not hasattr(request, 'data'):
                    if request_method == 'POST':
                        request.data = request.POST
                    else:
                        request.data = request.PUT  
                if request.data is None:
                    # In the case when Content-Type is not given or is invalid
                    raise ValidationError('Please make sure the header '+ \
                    '"Content-Type: application/json" is given')

        #    Bulk-PUT makes no sense at all, so it gives a ValidationError.
        #    Bulk-POST should only be allowed if it has been explicitly enabled
        #    by the ``bulk_create`` parameter.
        if request_method == 'PUT' and isinstance(request.data, list):
            raise ValidationError('Illegal Operation: PUT request with ' + \
                'array in request body')
        if request_method =='POST' and \
            not self.handler.bulk_create and \
            isinstance(request.data, list):
            raise ValidationError('API Handler does not allow bulk POST ' + \
                'requests')

        # Ok, the request has survived all the checks. At this point we strip
        # off the disallowed fields from the request body.
        if request_method in ('POST', 'PUT')\
        and self.handler.allowed_in_fields != self.handler.ALL_FIELDS:
            if isinstance(request.data, list):
                # We assume it's a list of dictionaries, and reject any non dicts.
                new_request_data = []
                for item in request.data:
                    if not isinstance(item, dict):
                        continue
                
                    clean_item = dict((key, value) for key, value in item.iteritems() \
                        if key in self.handler.allowed_in_fields)
        
                    new_request_data.append(clean_item)
                request.data = new_request_data                

            else:
                # Assume it's a dictionary
                request.data = dict((
                    (key, value) for key, value in request.data.iteritems() \
                    if key in self.handler.allowed_in_fields))
Beispiel #16
0
    def process_request(self, request, response, *args, **kwargs):
        """
        NB: Sends a `Vary` header so we don't cache requests
        that are different (OAuth stuff in `Authorization` header.)
        """
        rm = request.method.upper()

        # Django's internal mechanism doesn't pick up
        # on non POST request, so we trick it a little here.
        if rm in ("PUT", "DELETE",):
            coerce_put_post(request)

        actor, anonymous = self.authenticate(request, rm)

        result = None
        if anonymous is CHALLENGE:
            class ErrorHandler(BaseHandler):
                def error(self, *args, **kwargs):
                    pass

            for func in self.callmap.values():
                setattr(ErrorHandler, func, ErrorHandler.error)

            handler = ErrorHandler()
            meth = handler.error
            fields = ()
            response.data = actor(request)
        else:
            handler = actor
            meth = None
            fields = ()

        if not response.data:
            # Translate nested datastructs into `request.data` here.
            if rm in ('POST', 'PUT', 'DELETE',):
                try:
                    translate_mime(request)
                except MimerDataException:
                    raise PistonBadRequestException('Error deserializing request data.')
                if not hasattr(request, 'data'):
                    if rm == 'POST':
                        request.data = request.POST
                    elif rm == 'PUT':
                        request.data = request.PUT
                    elif rm == 'DELETE':
                        request.data = request.DELETE

                if not request.data:
                    # In the case where no data is provided, default to an empty
                    # dictionary. Many serializers do not deal with empty string data
                    # for deserialization.
                    setattr(request, rm, {})
                    request.data = {}

            if not rm in handler.allowed_methods:
                raise PistonMethodException(headers={'Allow': handler.allowed_methods})

            meth = getattr(handler, self.callmap.get(rm, ''), None)
            if not meth:
                raise PistonNotFoundException

            # Clean up the request object a bit, since we might
            # very well have `oauth_`-headers in there, and we
            # don't want to pass these along to the handler.
            request = self.cleanup_request(request)

            response.data = meth(request, *args, **kwargs)

            fields = handler.fields

            if hasattr(handler, 'list_fields') and isinstance(response.data, (list, tuple, QuerySet)):
                fields = handler.list_fields

        return handler, meth, fields, anonymous