def _cb_deferred(ret, request, p_ctx, others, resource, cb=True): 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) om = p_ctx.descriptor.out_message if cb and ((not issubclass(om, ComplexModelBase)) or len(om._type_info) <= 1): p_ctx.out_object = [ret] else: p_ctx.out_object = ret retval = None if isinstance(ret, PushBase): retval = _init_push(ret, request, p_ctx, others, resource) else: resource.http_transport.get_out_string(p_ctx) 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) request.registerProducer(producer, False) process_contexts(resource.http_transport, others, p_ctx) return retval
def handle_error(self, p_ctx, others, exc): self.spyne_tpt.get_out_string(p_ctx) if isinstance(exc, InternalError): error = self.spyne_tpt.OUT_RESPONSE_SERVER_ERROR else: error = self.spyne_tpt.OUT_RESPONSE_CLIENT_ERROR data = p_ctx.out_document[0] if isinstance(data, dict): data = list(data.values()) out_string = msgpack.packb([ error, msgpack.packb(data), ]) self.enqueue_outresp_data(id(p_ctx), out_string) p_ctx.transport.resp_length = len(out_string) p_ctx.close() try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
async def response( self, req: web.Request, p_ctx: AioMethodContext, others: list, error: typing.Optional[Fault] = None, ) -> web.StreamResponse: status_code = 200 if p_ctx.transport.resp_code: status_code = int(p_ctx.transport.resp_code[:3]) try: process_contexts(self, others, p_ctx, error=error) except Exception as e: logger.exception(e) p_ctx.close() return await self.make_streaming_response( req=req, content=p_ctx.out_string, status=status_code, chunked=self._chunked, headers=p_ctx.transport.resp_headers, )
def _cb_push(): process_contexts(self.http_transport, others, p_ctx) producer = _Producer(p_ctx.out_string, request) producer.deferred.addCallbacks(_cb_request_finished, _eb_request_finished) request.registerProducer(producer, False)
def handle_error(self, p_ctx, others, error, start_response): """Serialize errors to an iterable of strings and return them. :param p_ctx: Primary (non-aux) context. :param others: List if auxiliary contexts (can be empty). :param error: One of ctx.{in,out}_error. :param start_response: See the WSGI spec for more info. """ if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = \ p_ctx.out_protocol.fault_to_http_response_code(error) self.get_out_string(p_ctx) # consume the generator to get the length p_ctx.out_string = list(p_ctx.out_string) p_ctx.transport.resp_headers['Content-Length'] = \ str(sum((len(s) for s in p_ctx.out_string))) self.event_manager.fire_event('wsgi_exception', p_ctx) start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e) return chain(p_ctx.out_string, self.__finalize(p_ctx))
def _cb_deferred(ret, prot, p_ctx, others, nowrap=False): # if there is one return value or the output is bare (which means there # can't be anything other than 1 return value case) use the enclosing list. # otherwise, the return value is a tuple anyway, so leave it alone. if nowrap: p_ctx.out_object = ret else: if p_ctx.descriptor.is_out_bare(): p_ctx.out_object = [ret] else: if len(p_ctx.descriptor.out_message._type_info) > 1: p_ctx.out_object = ret else: p_ctx.out_object = [ret] try: prot.spyne_tpt.get_out_string(p_ctx) prot.spyne_tpt.pack(p_ctx) out_string = b''.join(p_ctx.out_string) p_ctx.transport.resp_length = len(out_string) prot.enqueue_outresp_data(id(p_ctx), out_string) except Exception as e: logger.exception(e) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot.spyne_tpt, others, p_ctx)
def serve_forever(self): """Runs the ZeroMQ server.""" while True: error = None initial_ctx = ZmqMethodContext(self) initial_ctx.in_string = [self.zmq_socket.recv()] contexts = self.generate_contexts(initial_ctx) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: p_ctx.out_object = p_ctx.in_error error = p_ctx.in_error else: self.get_in_object(p_ctx) if p_ctx.in_error: p_ctx.out_object = p_ctx.in_error error = p_ctx.in_error else: self.get_out_object(p_ctx) if p_ctx.out_error: p_ctx.out_object = p_ctx.out_error error = p_ctx.out_error self.get_out_string(p_ctx) process_contexts(self, others, error) self.zmq_socket.send(''.join(p_ctx.out_string)) p_ctx.close()
def _cb_deferred(ret, prot, p_ctx, others, nowrap=False): # if there is one return value or the output is bare (which means there # can't be anything other than 1 return value case) use the enclosing list. # otherwise, the return value is a tuple anyway, so leave it alone. if nowrap: p_ctx.out_object = ret else: if p_ctx.descriptor.is_out_bare(): p_ctx.out_object = [ret] else: if len(p_ctx.descriptor.out_message._type_info) > 1: p_ctx.out_object = ret else: p_ctx.out_object = [ret] try: prot.spyne_tpt.get_out_string(p_ctx) prot.spyne_tpt.pack(p_ctx) out_string = b''.join(p_ctx.out_string) p_ctx.transport.resp_length = len(out_string) prot.enqueue_outresp_data(id(p_ctx), out_string) except Exception as e: logger.exception(e) logger.error("%r", p_ctx) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot.spyne_tpt, others, p_ctx)
def response(self, response, p_ctx, others, error=None): """Populate response with transport headers and finalize it. :param response: Django HttpResponse. :param p_ctx: Primary (non-aux) context. :param others: List if auxiliary contexts (can be empty). :param error: One of ctx.{in,out}_error. :returns: Django HttpResponse """ for h, v in p_ctx.transport.resp_headers.items(): if v is not None: response[h] = v if p_ctx.transport.resp_code: response.status_code = int(p_ctx.transport.resp_code[:3]) try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e) p_ctx.close() return response
def handle_rpc_error(self, p_ctx, others, error, request): logger.error(error) 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 = p_ctx.out_protocol.fault_to_http_response_code(error) request.setResponseCode(int(resp_code[:3])) _set_response_headers(request, p_ctx.transport.resp_headers) # In case user code set its own out_* attributes before failing. p_ctx.out_document = None p_ctx.out_string = None p_ctx.out_object = error self.http_transport.get_out_string(p_ctx) retval = ''.join(p_ctx.out_string) p_ctx.close() process_contexts(self.http_transport, others, p_ctx, error=error) return retval
def serve_forever(self): """Runs the ZeroMQ server.""" while True: error = None initial_ctx = ZmqMethodContext(self) initial_ctx.in_string = [self.zmq_socket.recv()] contexts = self.generate_contexts(initial_ctx) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: p_ctx.out_object = p_ctx.in_error error = p_ctx.in_error else: self.get_in_object(p_ctx) if p_ctx.in_error: p_ctx.out_object = p_ctx.in_error error = p_ctx.in_error else: self.get_out_object(p_ctx) if p_ctx.out_error: p_ctx.out_object = p_ctx.out_error error = p_ctx.out_error self.get_out_string(p_ctx) process_contexts(self, others, error) self.zmq_socket.send(b''.join(p_ctx.out_string)) p_ctx.close()
def handle_rpc(self, request): initial_ctx = HttpMethodContext(self.http_transport, request, self.http_transport.app.out_protocol.mime_type) initial_ctx.in_string = [request.content.getvalue()] contexts = self.http_transport.generate_contexts(initial_ctx) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: return self.handle_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_error(p_ctx, others, p_ctx.in_error, request) else: self.http_transport.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, request) self.http_transport.get_out_string(p_ctx) process_contexts(self.http_transport, others, p_ctx) def _cb_request_finished(request): request.finish() producer = _Producer(p_ctx.out_string, request) producer.deferred.addErrback(err).addCallback(_cb_request_finished) request.registerProducer(producer, False) return NOT_DONE_YET
def handle_error(self, p_ctx, others, error): self.get_out_string(p_ctx) try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def _cb_deferred(retval, cb=True): if cb and len(p_ctx.descriptor.out_message._type_info) <= 1: p_ctx.out_object = [retval] else: p_ctx.out_object = retval tpt.get_out_string(p_ctx) self.sendFrame(opcode, ''.join(p_ctx.out_string), fin) p_ctx.close() process_contexts(tpt, others, p_ctx)
def _cb_deferred(ret, request, p_ctx, others, resource, cb=True): 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) om = p_ctx.descriptor.out_message single_class = None if cb and ((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 retval = NOT_DONE_YET if isinstance(ret, PushBase): retval = _init_push(ret, request, p_ctx, others, resource) 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: resource.http_transport.get_out_string(p_ctx) 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) request.registerProducer(producer, False) process_contexts(resource.http_transport, others, p_ctx) return retval
def handle_error(self, p_ctx, others, error, request): resp_code = self.http_transport.app.out_protocol \ .fault_to_http_response_code(error) request.setResponseCode(int(resp_code[:3])) p_ctx.out_object = error self.http_transport.get_out_string(p_ctx) process_contexts(self.http_transport, others, p_ctx, error=error) return ''.join(p_ctx.out_string)
def _cb_deferred(retval, request): if len(p_ctx.descriptor.out_message._type_info) <= 1: p_ctx.out_object = [retval] else: p_ctx.out_object = retval self.http_transport.get_out_string(p_ctx) process_contexts(self.http_transport, others, p_ctx) producer = _Producer(p_ctx.out_string, request) producer.deferred.addCallbacks(_cb_request_finished, _eb_request_finished) request.registerProducer(producer, False)
def _cb_deferred(retval, request, cb=True): if cb and len(p_ctx.descriptor.out_message._type_info) <= 1: p_ctx.out_object = [retval] else: p_ctx.out_object = retval self.http_transport.get_out_string(p_ctx) process_contexts(self.http_transport, others, p_ctx) producer = _Producer(p_ctx.out_string, request) producer.deferred.addCallbacks(_cb_request_finished, _eb_request_finished) request.registerProducer(producer, False)
def _cb_deferred(retval, request, p_ctx, others, resource, cb=True): if cb and len(p_ctx.descriptor.out_message._type_info) <= 1: p_ctx.out_object = [retval] else: p_ctx.out_object = retval resource.http_transport.get_out_string(p_ctx) process_contexts(resource.http_transport, others, p_ctx) producer = Producer(p_ctx.out_string, request) producer.deferred.addCallback(_cb_request_finished, p_ctx, others, resource) producer.deferred.addErrback(_eb_request_finished, p_ctx, others, resource) request.registerProducer(producer, False)
def handle_error(self, p_ctx, others, exc): self._transport.get_out_string(p_ctx) if isinstance(exc, InternalError): error = SERVER_ERROR else: error = CLIENT_ERROR out_string = msgpack.packb({error: msgpack.packb(p_ctx.out_document[0].values())}) self.transport.write(out_string) print "HE", repr(out_string) p_ctx.close() try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def handle_error(self, p_ctx, others, error, start_response): if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = \ self.app.out_protocol.fault_to_http_response_code(error) self.get_out_string(p_ctx) p_ctx.out_string = [''.join(p_ctx.out_string)] p_ctx.transport.resp_headers['Content-Length'] = str(len(p_ctx.out_string[0])) self.event_manager.fire_event('wsgi_exception', p_ctx) start_response(p_ctx.transport.resp_code, p_ctx.transport.resp_headers.items()) try: process_contexts(self, others, p_ctx, error=error) except Exception,e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def _cb_deferred(retval, prot, p_ctx, others, nowrap=False): if len(p_ctx.descriptor.out_message._type_info) > 1 or nowrap: p_ctx.out_object = retval else: p_ctx.out_object = [retval] try: prot._transport.get_out_string(p_ctx) p_ctx.out_string = list(p_ctx.out_string) print "PC", p_ctx.out_string prot.transport.write(''.join(p_ctx.out_string)) except: err(retval) finally: p_ctx.close() process_contexts(prot._transport, others, p_ctx)
def handle_rpc(self, request): initial_ctx = HttpMethodContext( self.http_transport, request, self.http_transport.app.out_protocol.mime_type) initial_ctx.in_string = [request.content.getvalue()] contexts = self.http_transport.generate_contexts(initial_ctx) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: return self.handle_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_error(p_ctx, others, p_ctx.in_error, request) else: self.http_transport.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, request) self.http_transport.get_out_string(p_ctx) process_contexts(self.http_transport, others, p_ctx) def _cb_request_finished(request): request.finish() p_ctx.close() def _eb_request_finished(request): err(request) p_ctx.close() producer = _Producer(p_ctx.out_string, request) producer.deferred.addErrback(_eb_request_finished).addCallback( _cb_request_finished) request.registerProducer(producer, False) return NOT_DONE_YET
def handle_error(self, p_ctx, others, error, start_response): if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = \ self.app.out_protocol.fault_to_http_response_code(error) self.get_out_string(p_ctx) p_ctx.out_string = [''.join(p_ctx.out_string)] p_ctx.transport.resp_headers['Content-Length'] = \ str(len(p_ctx.out_string[0])) self.event_manager.fire_event('wsgi_exception', p_ctx) start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) try: process_contexts(self, others, p_ctx, error=error) except Exception, e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def handle_error(self, p_ctx, others, exc): self._transport.get_out_string(p_ctx) if isinstance(exc, InternalError): error = OUT_RESPONSE_SERVER_ERROR else: error = OUT_RESPONSE_CLIENT_ERROR out_string = msgpack.packb([ error, msgpack.packb(p_ctx.out_document[0].values()), ]) self.transport.write(out_string) p_ctx.close() try: process_contexts(self, others, p_ctx, error=error) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def _cb_deferred(retval, prot, p_ctx, others, nowrap=False): if len(p_ctx.descriptor.out_message._type_info) > 1 or nowrap: p_ctx.out_object = retval else: p_ctx.out_object = [retval] try: prot._transport.get_out_string(p_ctx) out_string = msgpack.packb({NO_ERROR: "".join(p_ctx.out_string)}) prot.transport.write(out_string) print "PC", repr(out_string) except Exception as e: logger.exception(e) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot._transport, others, p_ctx)
def _cb_deferred(self, ret, p_ctx, others, nowrap=False): # this means callback is not invoked directly instead of as part of a # deferred chain if not nowrap: # if there is one return value or the output is bare (which means # there can't be anything other than 1 return value case) use the # enclosing list. otherwise, the return value is a tuple anyway, so # leave it be. if p_ctx.descriptor.is_out_bare(): p_ctx.out_object = [ret] else: if len(p_ctx.descriptor.out_message._type_info) > 1: p_ctx.out_object = ret else: p_ctx.out_object = [ret] if p_ctx.oob_ctx is not None: assert isinstance(p_ctx.oob_ctx.d, Deferred) p_ctx.oob_ctx.d.callback(p_ctx.out_object) return try: self.spyne_tpt.get_out_string(p_ctx) self.spyne_tpt.pack(p_ctx) out_string = b''.join(p_ctx.out_string) p_ctx.transport.resp_length = len(out_string) self.enqueue_outresp_data(id(p_ctx), out_string) except Exception as e: logger.exception(e) logger.error("%r", p_ctx) self.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(self.spyne_tpt, others, p_ctx)
def _cb_deferred(retval, prot, p_ctx, others, nowrap=False): if len(p_ctx.descriptor.out_message._type_info) > 1 or nowrap: p_ctx.out_object = retval else: p_ctx.out_object = [retval] try: prot._transport.get_out_string(p_ctx) prot._transport.pack(p_ctx) out_string = ''.join(p_ctx.out_string) prot.transport.write(out_string) except Exception as e: logger.exception(e) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot._transport, others, p_ctx)
def _cb_deferred(ret, prot, p_ctx, others, nowrap=False): # this means callback is not invoked directly instead of as part of a # deferred chain if not nowrap: # if there is one return value or the output is bare (which means there # can't be anything other than 1 return value case) use the enclosing # list. otherwise, the return value is a tuple anyway, so leave it be. if p_ctx.descriptor.is_out_bare(): p_ctx.out_object = [ret] else: if len(p_ctx.descriptor.out_message._type_info) > 1: p_ctx.out_object = ret else: p_ctx.out_object = [ret] if p_ctx.oob_ctx is not None: assert isinstance(p_ctx.oob_ctx.d, Deferred) p_ctx.oob_ctx.d.callback(p_ctx.out_object) return try: prot.spyne_tpt.get_out_string(p_ctx) prot.spyne_tpt.pack(p_ctx) out_string = b''.join(p_ctx.out_string) p_ctx.transport.resp_length = len(out_string) prot.enqueue_outresp_data(id(p_ctx), out_string) except Exception as e: logger.exception(e) logger.error("%r", p_ctx) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot.spyne_tpt, others, p_ctx)
def _cb_deferred(ret, prot, p_ctx, others, nowrap=False): if len(p_ctx.descriptor.out_message._type_info) > 1 or nowrap: p_ctx.out_object = ret else: p_ctx.out_object = [ret] try: prot.spyne_tpt.get_out_string(p_ctx) prot.spyne_tpt.pack(p_ctx) out_string = ''.join(p_ctx.out_string) prot.transport_write(out_string) p_ctx.transport.resp_length = len(out_string) except Exception as e: logger.exception(e) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot.spyne_tpt, others, p_ctx)
def _cb_deferred(ret, prot, p_ctx, others, nowrap=False): if len(p_ctx.descriptor.out_message._type_info) > 1 or nowrap: p_ctx.out_object = ret else: p_ctx.out_object = [ret] try: prot.spyne_tpt.get_out_string(p_ctx) prot.spyne_tpt.pack(p_ctx) out_string = b''.join(p_ctx.out_string) p_ctx.transport.resp_length = len(out_string) prot.enqueue_outresp_data(id(p_ctx), out_string) except Exception as e: logger.exception(e) prot.handle_error(p_ctx, others, InternalError(e)) finally: p_ctx.close() process_contexts(prot.spyne_tpt, others, p_ctx)
def _cb_push_finish(): process_contexts(self, (), p_ctx)
def _cb_push_finish(): process_contexts(self, others, p_ctx)
def _cb_push_finish(): p_ctx.out_stream.finish() process_contexts(self, others, p_ctx)
def _cb_deferred(ret, request, p_ctx, others, resource, cb=True): 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) om = p_ctx.descriptor.out_message single_class = None if cb: if p_ctx.descriptor.body_style in (BODY_STYLE_BARE, BODY_STYLE_EMPTY): 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 retval = NOT_DONE_YET p_ctx.out_stream = request if isinstance(ret, PushBase): retval = _init_push(ret, request, p_ctx, others, resource) 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: resource.http_transport.get_out_string(p_ctx) 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) request.registerProducer(producer, False) process_contexts(resource.http_transport, others, p_ctx) return retval
def _cb_push_finish(): p_ctx.out_stream.finish() process_contexts(resource.http_transport, others, p_ctx)
except TypeError: retval_iter = iter(p_ctx.out_string) try: first_chunk = retval_iter.next() except StopIteration: first_chunk = '' start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) retval = itertools.chain([first_chunk], retval_iter, self.__finalize(p_ctx)) try: process_contexts(self, others, p_ctx, error=None) except Exception, e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e) return retval def __finalize(self, p_ctx): p_ctx.close() self.event_manager.fire_event('wsgi_close', p_ctx) return () def __reconstruct_wsgi_request(self, http_env): """Reconstruct http payload using information in the http header."""
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
def handle_rpc(self, req_env, start_response): initial_ctx = WsgiMethodContext(self, req_env, self.app.out_protocol.mime_type) self.event_manager.fire_event('wsgi_call', initial_ctx) initial_ctx.in_string, in_string_charset = \ self.__reconstruct_wsgi_request(req_env) contexts = self.generate_contexts(initial_ctx, in_string_charset) p_ctx, others = contexts[0], contexts[1:] # TODO: rate limiting p_ctx.active = True if p_ctx.in_error: return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_in_object(p_ctx) if p_ctx.in_error: logger.error(p_ctx.in_error) return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) assert p_ctx.out_object is not None g = next(iter(p_ctx.out_object)) is_generator = len(p_ctx.out_object) == 1 and isgenerator(g) # if the out_object is a generator function, this hack makes the user # code run until first yield, which lets it set response headers and # whatnot before calling start_response. It's important to run this # here before serialization as the user function can also set output # protocol. Is there a better way? if is_generator: first_obj = next(g) p_ctx.out_object = (chain((first_obj, ), g), ) if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = HTTP_200 try: self.get_out_string(p_ctx) except Exception as e: logger.exception(e) p_ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) if isinstance(p_ctx.out_protocol, HttpRpc) and \ p_ctx.out_header_doc is not None: p_ctx.transport.resp_headers.update(p_ctx.out_header_doc) if p_ctx.descriptor and p_ctx.descriptor.mtom: # when there is more than one return type, the result is # encapsulated inside a list. when there's just one, the result # is returned in a non-encapsulated form. the apply_mtom always # expects the objects to be inside an iterable, hence the # following test. out_type_info = p_ctx.descriptor.out_message._type_info if len(out_type_info) == 1: p_ctx.out_object = [p_ctx.out_object] p_ctx.transport.resp_headers, p_ctx.out_string = apply_mtom( p_ctx.transport.resp_headers, p_ctx.out_string, p_ctx.descriptor.out_message._type_info.values(), p_ctx.out_object, ) self.event_manager.fire_event('wsgi_return', p_ctx) if self.chunked: # the user has not set a content-length, so we delete it as the # input is just an iterable. if 'Content-Length' in p_ctx.transport.resp_headers: del p_ctx.transport.resp_headers['Content-Length'] else: p_ctx.out_string = [''.join(p_ctx.out_string)] try: len(p_ctx.out_string) p_ctx.transport.resp_headers['Content-Length'] = \ str(sum([len(a) for a in p_ctx.out_string])) except TypeError: pass start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) retval = chain(p_ctx.out_string, self.__finalize(p_ctx)) try: process_contexts(self, others, p_ctx, error=None) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e) return retval
def handle_rpc(self, req_env, start_response): initial_ctx = WsgiMethodContext(self, req_env, self.app.out_protocol.mime_type) # implementation hook self.event_manager.fire_event('wsgi_call', initial_ctx) initial_ctx.in_string, in_string_charset = \ self.__reconstruct_wsgi_request(req_env) contexts = self.generate_contexts(initial_ctx, in_string_charset) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_in_object(p_ctx) if p_ctx.in_error: logger.error(p_ctx.in_error) return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = HTTP_200 self.get_out_string(p_ctx) if p_ctx.descriptor and p_ctx.descriptor.mtom: # when there is more than one return type, the result is # encapsulated inside a list. when there's just one, the result # is returned in a non-encapsulated form. the apply_mtom always # expects the objects to be inside an iterable, hence the # following test. out_type_info = p_ctx.descriptor.out_message._type_info if len(out_type_info) == 1: out_object = [out_object] p_ctx.transport.resp_headers, p_ctx.out_string = apply_mtom( p_ctx.transport.resp_headers, p_ctx.out_string, p_ctx.descriptor.out_message._type_info.values(), out_object ) # implementation hook self.event_manager.fire_event('wsgi_return', p_ctx) # the client has not set a content-length, so we delete it as the input # is just an iterable. if self.chunked: if 'Content-Length' in p_ctx.transport.resp_headers: del p_ctx.transport.resp_headers['Content-Length'] else: p_ctx.out_string = [''.join(p_ctx.out_string)] # if the out_string is a generator function, this hack lets the user # code run until first yield, which lets it set response headers and # whatnot beforce calling start_response. yes it causes an additional # copy of the first fragment of the response to be made, but if you know # a better way of having generator functions execute until first yield, # just let us know. try: len(p_ctx.out_string) # iterator? # nope p_ctx.transport.resp_headers['Content-Length'] = \ str(sum([len(a) for a in p_ctx.out_string])) start_response(p_ctx.transport.resp_code, p_ctx.transport.resp_headers.items()) retval = p_ctx.out_string except TypeError: retval_iter = iter(p_ctx.out_string) retval = retval_iter.next() start_response(p_ctx.transport.resp_code, p_ctx.transport.resp_headers.items()) retval = itertools.chain([retval], retval_iter) try: process_contexts(self, others, p_ctx, error=None) except Exception, e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)
def handle_rpc(self, req_env, start_response): initial_ctx = WsgiMethodContext(self, req_env, self.app.out_protocol.mime_type) self.event_manager.fire_event('wsgi_call', initial_ctx) initial_ctx.in_string, in_string_charset = \ self.__reconstruct_wsgi_request(req_env) contexts = self.generate_contexts(initial_ctx, in_string_charset) p_ctx, others = contexts[0], contexts[1:] # TODO: rate limiting p_ctx.active = True if p_ctx.in_error: return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_in_object(p_ctx) if p_ctx.in_error: logger.error(p_ctx.in_error) return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) assert p_ctx.out_object is not None g = next(iter(p_ctx.out_object)) is_generator = len(p_ctx.out_object) == 1 and isgenerator(g) # if the out_object is a generator function, this hack makes the user # code run until first yield, which lets it set response headers and # whatnot before calling start_response. It's important to run this # here before serialization as the user function can also set output # protocol. Is there a better way? if is_generator: first_obj = next(g) p_ctx.out_object = ( chain((first_obj,), g), ) if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = HTTP_200 try: self.get_out_string(p_ctx) except Exception as e: logger.exception(e) p_ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) if isinstance(p_ctx.out_protocol, HttpRpc) and \ p_ctx.out_header_doc is not None: p_ctx.transport.resp_headers.update(p_ctx.out_header_doc) if p_ctx.descriptor and p_ctx.descriptor.mtom: # when there is more than one return type, the result is # encapsulated inside a list. when there's just one, the result # is returned in a non-encapsulated form. the apply_mtom always # expects the objects to be inside an iterable, hence the # following test. out_type_info = p_ctx.descriptor.out_message._type_info if len(out_type_info) == 1: p_ctx.out_object = [p_ctx.out_object] p_ctx.transport.resp_headers, p_ctx.out_string = apply_mtom( p_ctx.transport.resp_headers, p_ctx.out_string, p_ctx.descriptor.out_message._type_info.values(), p_ctx.out_object, ) self.event_manager.fire_event('wsgi_return', p_ctx) if self.chunked: # the user has not set a content-length, so we delete it as the # input is just an iterable. if 'Content-Length' in p_ctx.transport.resp_headers: del p_ctx.transport.resp_headers['Content-Length'] else: p_ctx.out_string = [''.join(p_ctx.out_string)] try: len(p_ctx.out_string) p_ctx.transport.resp_headers['Content-Length'] = \ str(sum([len(a) for a in p_ctx.out_string])) except TypeError: pass start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) retval = chain(p_ctx.out_string, self.__finalize(p_ctx)) try: process_contexts(self, others, p_ctx, error=None) except Exception as e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e) return retval
def handle_rpc(self, req_env, start_response): initial_ctx = WsgiMethodContext(self, req_env, self.app.out_protocol.mime_type) # implementation hook self.event_manager.fire_event('wsgi_call', initial_ctx) initial_ctx.in_string, in_string_charset = \ self.__reconstruct_wsgi_request(req_env) contexts = self.generate_contexts(initial_ctx, in_string_charset) p_ctx, others = contexts[0], contexts[1:] if p_ctx.in_error: return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_in_object(p_ctx) if p_ctx.in_error: logger.error(p_ctx.in_error) return self.handle_error(p_ctx, others, p_ctx.in_error, start_response) self.get_out_object(p_ctx) if p_ctx.out_error: return self.handle_error(p_ctx, others, p_ctx.out_error, start_response) if p_ctx.transport.resp_code is None: p_ctx.transport.resp_code = HTTP_200 self.get_out_string(p_ctx) if isinstance(self.app.out_protocol, HttpRpc) and \ p_ctx.out_header_doc is not None: p_ctx.transport.resp_headers.update(p_ctx.out_header_doc) if p_ctx.descriptor and p_ctx.descriptor.mtom: # when there is more than one return type, the result is # encapsulated inside a list. when there's just one, the result # is returned in a non-encapsulated form. the apply_mtom always # expects the objects to be inside an iterable, hence the # following test. out_type_info = p_ctx.descriptor.out_message._type_info if len(out_type_info) == 1: out_object = [out_object] p_ctx.transport.resp_headers, p_ctx.out_string = apply_mtom( p_ctx.transport.resp_headers, p_ctx.out_string, p_ctx.descriptor.out_message._type_info.values(), out_object) # implementation hook self.event_manager.fire_event('wsgi_return', p_ctx) if self.chunked: # the client has not set a content-length, so we delete it as the # input is just an iterable. if 'Content-Length' in p_ctx.transport.resp_headers: del p_ctx.transport.resp_headers['Content-Length'] else: p_ctx.out_string = [''.join(p_ctx.out_string)] # if the out_string is a generator function, this hack lets the user # code run until first yield, which lets it set response headers and # whatnot before calling start_response. Is there a better way? try: len(p_ctx.out_string) # generator? # nope p_ctx.transport.resp_headers['Content-Length'] = \ str(sum([len(a) for a in p_ctx.out_string])) start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) retval = itertools.chain(p_ctx.out_string, self.__finalize(p_ctx)) except TypeError: retval_iter = iter(p_ctx.out_string) try: first_chunk = retval_iter.next() except StopIteration: first_chunk = '' start_response(p_ctx.transport.resp_code, _gen_http_headers(p_ctx.transport.resp_headers)) retval = itertools.chain([first_chunk], retval_iter, self.__finalize(p_ctx)) try: process_contexts(self, others, p_ctx, error=None) except Exception, e: # Report but ignore any exceptions from auxiliary methods. logger.exception(e)