async def _recv_response(self, reader, writer): """ wait response and put it in response_mapping, than notify the invoke coro :param reader: :return: """ while True: pkg = None try: fixed_header_bs = await reader.readexactly( BoltResponse.bolt_header_size()) header = BoltResponse.bolt_header_from_stream(fixed_header_bs) bs = await reader.readexactly(header['class_len'] + header['header_len'] + header['content_len']) pkg = BoltResponse.bolt_content_from_stream(bs, header) if pkg.class_name != BoltResponse.class_name: raise ServerError("wrong class_name:[{}]".format( pkg.class_name)) if pkg.cmdcode == CMDCODE.HEARTBEAT: continue elif pkg.cmdcode == CMDCODE.REQUEST: # raise error, the connection will be dropped raise ServerError("wrong cmdcode:[{}]".format(pkg.cmdcode)) if pkg.respstatus != RESPSTATUS.SUCCESS: raise ServerError.from_statuscode(pkg.respstatus) if pkg.request_id not in self.request_mapping: continue self.response_mapping[pkg.request_id] = pkg except PyboltError as e: logger.error(e) except (asyncio.CancelledError, EOFError, ConnectionResetError) as e: logger.error(e) writer.close() break except Exception: logger.error(traceback.format_exc()) writer.close() break finally: with suppress(AttributeError, KeyError): # wake up the coro event = self.request_mapping.pop(pkg.request_id) event.set()
def test_repr(self): p = BoltResponse(SofaHeader(a='1', b='2'), b"cdefgab", ptype=PTYPE.ONEWAY, request_id=0, cmdcode=CMDCODE.HEARTBEAT, respstatus=1) print(p) s = p.to_stream() pr = BoltResponse.from_stream(s) self.assertNotEqual(id(p), id(pr)) self.assertEqual(p.header, pr.header) self.assertEqual(p.content, pr.content) self.assertEqual(p.cmdcode, pr.cmdcode) self.assertEqual(p.request_id, pr.request_id) print(pr) p = BoltRequest(SofaHeader(a='1', b='2'), b"jklmnhi", ptype=PTYPE.ONEWAY, request_id=0, cmdcode=CMDCODE.HEARTBEAT, timeout=-1) print(p) s = p.to_stream() pr = BoltRequest.from_stream(s) self.assertNotEqual(id(p), id(pr)) self.assertEqual(p.header, pr.header) self.assertEqual(p.content, pr.content) self.assertEqual(p.cmdcode, pr.cmdcode) self.assertEqual(p.request_id, pr.request_id) print(pr)
def handle(self): try: fixed_header_bs = self._readexactly(BoltRequest.bolt_header_size()) header = BoltRequest.bolt_header_from_stream(fixed_header_bs) call_type = header['ptype'] cmdcode = header['cmdcode'] class_name = self._readexactly(header['class_len']) bs = self._readexactly(header['header_len']) sofa_header = SofaHeader.from_bytes(bs) body = self._readexactly(header['content_len']) request_id = header['request_id'] if cmdcode == CMDCODE.HEARTBEAT: self.wfile.write(HeartbeatResponse.response_to(request_id).to_stream()) self.wfile.flush() return if cmdcode == CMDCODE.RESPONSE: raise ClientError("wrong cmdcode:[{}]".format(cmdcode)) if class_name != "com.alipay.sofa.rpc.core.request.SofaRequest".encode(): raise ClientError("wrong class_name:[{}]".format(class_name)) service = sofa_header.get('sofa_head_target_service') or sofa_header.get('service') if not service: self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream()) self.wfile.flush() logger.error("Missing service name in sofa header [{}]".format(sofa_header)) return method = sofa_header.get('sofa_head_method_name') if not method: self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream()) self.wfile.flush() logger.error("Missing method name in sofa header [{}]".format(sofa_header)) return spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header) # call servicehandler ret = self.service_handler.handle_request(spanctx, service, method, body) self.wfile.write(BoltResponse.response_to(ret, request_id=request_id).to_stream()) self.wfile.flush() except OSError as e: if e.errno != ECONNRESET: raise except Exception as e: logger.error(traceback.format_exc())
def test_from_stream(self): bs = b'\x01\x00\x00\x02\x01\x00\x00\x00\x84\x0b\x00\x00\x00\x2e\x00\x00\x00\x00\x00\x03\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x73\x6f\x66\x61\x2e\x72\x70\x63\x2e\x63\x6f\x72\x65\x2e\x72\x65\x73\x70\x6f\x6e\x73\x65\x2e\x53\x6f\x66\x61\x52\x65\x73\x70\x6f\x6e\x73\x65\x0a\x01\x61' p = BoltResponse.from_stream(bs) self.assertEqual(p.body_len, len(bs) - p.bolt_header_size()) print(p.content) re = SampleServicePbResult_pb2.SampleServicePbResult() re.ParseFromString(p.content) # print(p) print(re.result) self.assertEqual(re.result, 'a') bs = b'\x01\x01\x00\x01\x01\x00\x00\x00\x6d\x0b\x00\x00\x00\x64\x00\x2c\x02\xe6\x00\x00\x00\x03\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x73\x6f\x66\x61\x2e\x72\x70\x63\x2e\x63\x6f\x72\x65\x2e\x72\x65\x71\x75\x65\x73\x74\x2e\x53\x6f\x66\x61\x52\x65\x71\x75\x65\x73\x74\x00\x00\x00\x18\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x74\x61\x72\x67\x65\x74\x5f\x73\x65\x72\x76\x69\x63\x65\x00\x00\x00\x3b\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x72\x70\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x73\x65\x72\x76\x69\x63\x65\x2e\x66\x61\x63\x61\x64\x65\x2e\x70\x62\x2e\x53\x61\x6d\x70\x6c\x65\x53\x65\x72\x76\x69\x63\x65\x50\x62\x3a\x31\x2e\x30\x00\x00\x00\x1b\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x52\x70\x63\x49\x64\x00\x00\x00\x01\x30\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x54\x69\x6d\x65\x6f\x75\x74\x00\x00\x00\x03\x31\x30\x30\x00\x00\x00\x1d\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x54\x72\x61\x63\x65\x49\x64\x00\x00\x00\x1e\x30\x62\x61\x36\x31\x36\x61\x31\x31\x35\x32\x33\x32\x35\x31\x38\x31\x39\x31\x31\x34\x31\x30\x30\x32\x31\x38\x37\x33\x38\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x49\x64\x63\x00\x00\x00\x03\x64\x65\x76\x00\x00\x00\x1e\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x49\x70\x00\x00\x00\x0d\x31\x31\x2e\x31\x36\x36\x2e\x32\x32\x2e\x31\x36\x31\x00\x00\x00\x1e\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x50\x65\x6e\x41\x74\x74\x72\x73\x00\x00\x00\x00\x00\x00\x00\x1b\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x55\x49\x44\x00\x00\x00\x00\x00\x00\x00\x20\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x5a\x6f\x6e\x65\x00\x00\x00\x05\x47\x5a\x30\x30\x42\x00\x00\x00\x14\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x74\x61\x72\x67\x65\x74\x5f\x61\x70\x70\x00\x00\x00\x04\x62\x61\x72\x31\x00\x00\x00\x07\x73\x65\x72\x76\x69\x63\x65\x00\x00\x00\x3b\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x72\x70\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x73\x65\x72\x76\x69\x63\x65\x2e\x66\x61\x63\x61\x64\x65\x2e\x70\x62\x2e\x53\x61\x6d\x70\x6c\x65\x53\x65\x72\x76\x69\x63\x65\x50\x62\x3a\x31\x2e\x30\x00\x00\x00\x19\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x45\x6c\x61\x73\x74\x69\x63\x00\x00\x00\x01\x46\x00\x00\x00\x1d\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x79\x73\x50\x65\x6e\x41\x74\x74\x72\x73\x00\x00\x00\x00\x00\x00\x00\x22\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x54\x61\x72\x67\x65\x74\x5a\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x41\x70\x70\x00\x00\x00\x03\x66\x6f\x6f\x00\x00\x00\x15\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x6d\x65\x74\x68\x6f\x64\x5f\x6e\x61\x6d\x65\x00\x00\x00\x05\x68\x65\x6c\x6c\x6f\x0a\x01\x61' p = BoltRequest.from_stream(bs) print(p.header) re = SampleServicePbRequest_pb2.SampleServicePbRequest() re.ParseFromString(p.content) print(re) self.assertEqual(re.name, "a")
async def _dispatch(self, call_type, request_id, sofa_header, body, *, timeout_ms, codec, writer): """send request to handler""" service = sofa_header.get( 'sofa_head_target_service') or sofa_header.get('service') if not service: await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR, codec=codec).to_stream(), ) logger.error( "Missing service name in sofa header [{}]".format(sofa_header)) return method = sofa_header.get('sofa_head_method_name') if not method: await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR, codec=codec).to_stream()) logger.error( "Missing method name in sofa header [{}]".format(sofa_header)) return spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header) try: future = self.handler.handle_request(spanctx, service, method, body) except NoProcessorError: await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.NO_PROCESSOR, codec=codec).to_stream(), ) return except Exception: await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.SERVER_EXCEPTION, codec=codec).to_stream(), ) return if PTYPE.ONEWAY == call_type: # Just return future return future try: afut = asyncio.wrap_future(future) result = await asyncio.wait_for( afut, timeout_ms / 1000 if timeout_ms > 0 else None) except (asyncio.CancelledError, asyncio.TimeoutError) as e: logger.error( "Task run cancelled/timeout in {}ms, service:[{}]: error:[{}]". format(timeout_ms, service, e)) await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.TIMEOUT, codec=codec).to_stream(), ) return except Exception: logger.error(traceback.format_exc()) await self._write_msg( writer, FailResponse.response_to(request_id, RESPSTATUS.UNKNOWN, codec=codec).to_stream(), ) return if result: header = dict() tracer.inject(spanctx, opentracing.Format.TEXT_MAP, header) pkg = BoltResponse.response_to(result, request_id=request_id, codec=codec) try: await self._write_msg(writer, pkg.to_stream()) except Exception: logger.error(traceback.format_exc())