Esempio n. 1
0
    def handle_rpc(self, request):
        initial_ctx = TwistedHttpMethodContext(self.http_transport, request,
                                 self.http_transport.app.out_protocol.mime_type)

        if _has_fd(request.content):
            f = request.content

            # it's best to avoid empty mappings.
            if fstat(f.fileno()).st_size == 0:
                initial_ctx.in_string = ['']
            else:
                initial_ctx.in_string = [mmap(f.fileno(), 0)]
        else:
            request.content.seek(0)
            initial_ctx.in_string = [request.content.read()]

        initial_ctx.transport.file_info = _get_file_info(initial_ctx)

        contexts = self.http_transport.generate_contexts(initial_ctx)
        p_ctx, others = contexts[0], contexts[1:]

        p_ctx.active = True
        p_ctx.out_stream = request
        # TODO: Rate limiting
        p_ctx.active = True

        if p_ctx.in_error:
            return self.handle_rpc_error(p_ctx, others, p_ctx.in_error, request)

        else:
            self.http_transport.get_in_object(p_ctx)

            if p_ctx.in_error:
                return self.handle_rpc_error(p_ctx, others, p_ctx.in_error,
                                                                        request)

            self.http_transport.get_out_object(p_ctx)
            if p_ctx.out_error:
                return self.handle_rpc_error(p_ctx, others, p_ctx.out_error,
                                                                        request)

        ret = p_ctx.out_object[0]
        retval = NOT_DONE_YET
        if isinstance(ret, Deferred):
            ret.addCallback(_cb_deferred, request, p_ctx, others, resource=self)
            ret.addErrback(_eb_deferred, request, p_ctx, others, resource=self)

        elif isinstance(ret, PushBase):
            self.http_transport.init_root_push(ret, p_ctx, others)

        else:
            try:
                retval = _cb_deferred(p_ctx.out_object, request, p_ctx, others,
                                                                 self, cb=False)
            except Exception as e:
                logger_server.exception(e)
                _eb_deferred(Failure(), request, p_ctx, others, resource=self)

        return retval
Esempio n. 2
0
def _eb_deferred(ret, request, p_ctx, others, resource):
    app = p_ctx.app

    # DRY this with what's in Application.process_request
    if issubclass(ret.type, Redirect):
        try:
            ret.value.do_redirect()

            # Now that the processing is switched to the outgoing message,
            # point ctx.protocol to ctx.out_protocol
            p_ctx.protocol = p_ctx.outprot_ctx

            _cb_deferred(None, request, p_ctx, others, resource, cb=False)

            # fire events
            app.event_manager.fire_event('method_redirect', p_ctx)
            if p_ctx.service_class is not None:
                p_ctx.service_class.event_manager.fire_event(
                    'method_redirect', p_ctx)

        except Exception as e:
            logger_server.exception(e)
            p_ctx.out_error = Fault('Server',
                                    get_fault_string_from_exception(e))

            # fire events
            app.event_manager.fire_event('method_redirect_exception', p_ctx)
            if p_ctx.service_class is not None:
                p_ctx.service_class.event_manager.fire_event(
                    'method_redirect_exception', p_ctx)

    elif issubclass(ret.type, Fault):
        p_ctx.out_error = ret.value

        ret = resource.handle_rpc_error(p_ctx, others, p_ctx.out_error,
                                        request)

        # fire events
        app.event_manager.fire_event('method_exception_object', p_ctx)
        if p_ctx.service_class is not None:
            p_ctx.service_class.event_manager.fire_event(
                'method_exception_object', p_ctx)

        request.write(ret)

    else:
        p_ctx.out_error = ret.value
        ret.printTraceback()
        p_ctx.out_error = InternalError(ret.value)

        # fire events
        app.event_manager.fire_event('method_exception_object', p_ctx)
        if p_ctx.service_class is not None:
            p_ctx.service_class.event_manager.fire_event(
                'method_exception_object', p_ctx)

    request.finish()
Esempio n. 3
0
def _eb_deferred(ret, request, p_ctx, others, resource):
    app = p_ctx.app

    # DRY this with what's in Application.process_request
    if issubclass(ret.type, Redirect):
        try:
            ret.value.do_redirect()

            # Now that the processing is switched to the outgoing message,
            # point ctx.protocol to ctx.out_protocol
            p_ctx.protocol = p_ctx.outprot_ctx

            _cb_deferred(None, request, p_ctx, others, resource, cb=False)

            # fire events
            app.event_manager.fire_event('method_redirect', p_ctx)
            if p_ctx.service_class is not None:
                p_ctx.service_class.event_manager.fire_event(
                    'method_redirect', p_ctx)

        except Exception as e:
            logger_server.exception(e)
            p_ctx.out_error = Fault('Server', get_fault_string_from_exception(e))

            # fire events
            app.event_manager.fire_event('method_redirect_exception', p_ctx)
            if p_ctx.service_class is not None:
                p_ctx.service_class.event_manager.fire_event(
                    'method_redirect_exception', p_ctx)

    elif issubclass(ret.type, Fault):
        p_ctx.out_error = ret.value

        ret = resource.handle_rpc_error(p_ctx, others, p_ctx.out_error, request)

        # fire events
        app.event_manager.fire_event('method_exception_object', p_ctx)
        if p_ctx.service_class is not None:
            p_ctx.service_class.event_manager.fire_event(
                                               'method_exception_object', p_ctx)

        request.write(ret)

    else:
        p_ctx.out_error = ret.value
        ret.printTraceback()
        p_ctx.out_error = InternalError(ret.value)

        # fire events
        app.event_manager.fire_event('method_exception_object', p_ctx)
        if p_ctx.service_class is not None:
            p_ctx.service_class.event_manager.fire_event(
                                               'method_exception_object', p_ctx)

    request.finish()
Esempio n. 4
0
def _eb_deferred(ret, request, p_ctx, others, resource):
    # DRY this with what's in Application.process_request
    if ret.check(Redirect):
        try:
            ret.value.do_redirect()

            # Now that the processing is switched to the outgoing message,
            # point ctx.protocol to ctx.out_protocol
            p_ctx.protocol = p_ctx.outprot_ctx

            _cb_deferred(None, request, p_ctx, others, resource, cb=False)

            p_ctx.fire_event('method_redirect')

        except Exception as e:
            logger_server.exception(e)
            p_ctx.out_error = Fault('Server',
                                    get_fault_string_from_exception(e))

            p_ctx.fire_event('method_redirect_exception')

    elif ret.check(Fault):
        p_ctx.out_error = ret.value

        ret = resource.handle_rpc_error(p_ctx, others, p_ctx.out_error,
                                        request)

        p_ctx.fire_event('method_exception_object')

        request.write(ret)

    else:
        p_ctx.out_error = InternalError(ret.value)
        logger.error(ret.getTraceback())

        ret = resource.handle_rpc_error(p_ctx, others, p_ctx.out_error,
                                        request)

        p_ctx.fire_event('method_exception_object')

        request.write(ret)

    request.finish()
Esempio n. 5
0
def _cb_deferred(ret, request, p_ctx, others, resource, cb=True):
    ### set response headers
    resp_code = p_ctx.transport.resp_code

    # If user code set its own response code, don't touch it.
    if resp_code is None:
        resp_code = HTTP_200
    request.setResponseCode(int(resp_code[:3]))

    _set_response_headers(request, p_ctx.transport.resp_headers)

    ### normalize response data
    om = p_ctx.descriptor.out_message
    single_class = None
    if cb:
        if p_ctx.descriptor.is_out_bare():
            p_ctx.out_object = [ret]

        elif (not issubclass(om, ComplexModelBase)) or len(om._type_info) <= 1:
            p_ctx.out_object = [ret]
            if len(om._type_info) == 1:
                single_class, = om._type_info.values()
        else:
            p_ctx.out_object = ret
    else:
        p_ctx.out_object = ret

    ### start response
    retval = NOT_DONE_YET

    if isinstance(ret, PushBase):
        resource.http_transport.init_root_push(ret, p_ctx, others)

    elif ((isclass(om) and issubclass(om, File)) or
          (isclass(single_class) and issubclass(single_class, File))) and \
         isinstance(p_ctx.out_protocol, HttpRpc) and \
                                      getattr(ret, 'abspath', None) is not None:

        file = static.File(ret.abspath,
                           defaultType=str(ret.type)
                           or 'application/octet-stream')
        retval = _render_file(file, request)
        if retval != NOT_DONE_YET and cb:
            request.write(retval)
            request.finish()
            p_ctx.close()
        else:

            def _close_only_context(ret):
                p_ctx.close()

            request.notifyFinish() \
                .addCallback(_close_only_context) \
                .addErrback(_eb_request_finished, request, p_ctx) \
                .addErrback(log_and_let_go, logger)

    else:
        ret = resource.http_transport.get_out_string(p_ctx)

        if not isinstance(ret, Deferred):
            producer = Producer(p_ctx.out_string, request)
            producer.deferred \
                .addCallback(_cb_request_finished, request, p_ctx) \
                .addErrback(_eb_request_finished, request, p_ctx) \
                .addErrback(log_and_let_go, logger)

            try:
                request.registerProducer(producer, False)
            except Exception as e:
                logger_server.exception(e)
                try:
                    _eb_deferred(Failure(), request, p_ctx, others, resource)
                except Exception as e:
                    logger_server.exception(e)
                    raise

        else:

            def _cb(ret):
                if isinstance(ret, Deferred):
                    return ret \
                        .addCallback(_cb) \
                        .addErrback(_eb_request_finished, request, p_ctx) \
                        .addErrback(log_and_let_go, logger)
                else:
                    return _cb_request_finished(ret, request, p_ctx)

            ret \
                .addCallback(_cb) \
                .addErrback(_eb_request_finished, request, p_ctx) \
                .addErrback(log_and_let_go, logger)

    process_contexts(resource.http_transport, others, p_ctx)

    return retval
Esempio n. 6
0
File: http.py Progetto: knoxsp/spyne
def _cb_deferred(ret, request, p_ctx, others, resource, cb=True):
    ### set response headers
    resp_code = p_ctx.transport.resp_code

    # If user code set its own response code, don't touch it.
    if resp_code is None:
        resp_code = HTTP_200
    request.setResponseCode(int(resp_code[:3]))

    _set_response_headers(request, p_ctx.transport.resp_headers)

    ### normalize response data
    om = p_ctx.descriptor.out_message
    single_class = None
    if cb:
        if p_ctx.descriptor.is_out_bare():
            p_ctx.out_object = [ret]

        elif (not issubclass(om, ComplexModelBase)) or len(om._type_info) <= 1:
            p_ctx.out_object = [ret]
            if len(om._type_info) == 1:
                single_class, = om._type_info.values()
        else:
            p_ctx.out_object = ret
    else:
        p_ctx.out_object = ret

    ### start response
    retval = NOT_DONE_YET

    if isinstance(ret, PushBase):
        resource.http_transport.init_root_push(ret, p_ctx, others)

    elif ((isclass(om) and issubclass(om, File)) or
          (isclass(single_class) and issubclass(single_class, File))) and \
         isinstance(p_ctx.out_protocol, HttpRpc) and \
                                      getattr(ret, 'abspath', None) is not None:

        file = static.File(ret.abspath,
                        defaultType=str(ret.type) or 'application/octet-stream')
        retval = _render_file(file, request)
        if retval != NOT_DONE_YET and cb:
            request.write(retval)
            request.finish()
            p_ctx.close()
        else:
            def _close_only_context(ret):
                p_ctx.close()

            request.notifyFinish().addCallback(_close_only_context)
            request.notifyFinish().addErrback(_eb_request_finished, request, p_ctx)

    else:
        ret = resource.http_transport.get_out_string(p_ctx)

        if not isinstance(ret, Deferred):
            producer = Producer(p_ctx.out_string, request)
            producer.deferred.addCallback(_cb_request_finished, request, p_ctx)
            producer.deferred.addErrback(_eb_request_finished, request, p_ctx)

            try:
                request.registerProducer(producer, False)
            except Exception as e:
                logger_server.exception(e)
                _eb_deferred(Failure(), request, p_ctx, others, resource)

        else:
            def _cb(ret):
                if isinstance(ret, Deferred):
                    return ret \
                        .addCallback(_cb) \
                        .addErrback(_eb_request_finished, request, p_ctx)
                else:
                    return _cb_request_finished(ret, request, p_ctx)

            ret \
                .addCallback(_cb) \
                .addErrback(_eb_request_finished, request, p_ctx)

    process_contexts(resource.http_transport, others, p_ctx)

    return retval