##// END OF EJS Templates
wireprotov2: change behavior of error frame...
Gregory Szorc -
r37744:0c184ca5 default
parent child Browse files
Show More
@@ -688,23 +688,44 b' 0x02'
688 688
689 689 The ``0x01`` flag is mutually exclusive with the ``0x02`` flag.
690 690
691 Error Response (``0x05``)
691 Error Occurred (``0x05``)
692 692 -------------------------
693 693
694 An error occurred when processing a request. This could indicate
695 a protocol-level failure or an application level failure depending
696 on the flags for this message type.
694 Some kind of error occurred.
695
696 There are 3 general kinds of failures that can occur:
697 697
698 The payload for this type is an error message that should be
699 displayed to the user.
698 * Command error encountered before any response issued
699 * Command error encountered after a response was issued
700 * Protocol or stream level error
701
702 This frame type is used to capture the latter cases. (The general
703 command error case is handled by the leading CBOR map in
704 ``Command Response`` frames.)
705
706 The payload of this frame contains a CBOR map detailing the error. That
707 map has the following bytestring keys:
700 708
701 The following flag values are defined for this type:
709 type
710 (bytestring) The overall type of error encountered. Can be one of the
711 following values:
712
713 protocol
714 A protocol-level error occurred. This typically means someone
715 is violating the framing protocol semantics and the server is
716 refusing to proceed.
702 717
703 0x01
704 The error occurred at the transport/protocol level. If set, the
705 connection should be closed.
706 0x02
707 The error occurred at the application level. e.g. invalid command.
718 server
719 A server-level error occurred. This typically indicates some kind of
720 logic error on the server, likely the fault of the server.
721
722 command
723 A command-level error, likely the fault of the client.
724
725 message
726 (array of maps) A richly formatted message that is intended for
727 human consumption. See the ``Human Output Side-Channel`` frame
728 section for a description of the format of this data structure.
708 729
709 730 Human Output Side-Channel (``0x06``)
710 731 ------------------------------------
@@ -87,20 +87,12 b' FLAGS_COMMAND_RESPONSE = {'
87 87 b'eos': FLAG_COMMAND_RESPONSE_EOS,
88 88 }
89 89
90 FLAG_ERROR_RESPONSE_PROTOCOL = 0x01
91 FLAG_ERROR_RESPONSE_APPLICATION = 0x02
92
93 FLAGS_ERROR_RESPONSE = {
94 b'protocol': FLAG_ERROR_RESPONSE_PROTOCOL,
95 b'application': FLAG_ERROR_RESPONSE_APPLICATION,
96 }
97
98 90 # Maps frame types to their available flags.
99 91 FRAME_TYPE_FLAGS = {
100 92 FRAME_TYPE_COMMAND_REQUEST: FLAGS_COMMAND_REQUEST,
101 93 FRAME_TYPE_COMMAND_DATA: FLAGS_COMMAND_DATA,
102 94 FRAME_TYPE_COMMAND_RESPONSE: FLAGS_COMMAND_RESPONSE,
103 FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE,
95 FRAME_TYPE_ERROR_RESPONSE: {},
104 96 FRAME_TYPE_TEXT_OUTPUT: {},
105 97 FRAME_TYPE_PROGRESS: {},
106 98 FRAME_TYPE_STREAM_SETTINGS: {},
@@ -394,20 +386,19 b' def createcommandresponseframesfrombytes'
394 386 if done:
395 387 break
396 388
397 def createerrorframe(stream, requestid, msg, protocol=False, application=False):
389 def createerrorframe(stream, requestid, msg, errtype):
398 390 # TODO properly handle frame size limits.
399 391 assert len(msg) <= DEFAULT_MAX_FRAME_SIZE
400 392
401 flags = 0
402 if protocol:
403 flags |= FLAG_ERROR_RESPONSE_PROTOCOL
404 if application:
405 flags |= FLAG_ERROR_RESPONSE_APPLICATION
393 payload = cbor.dumps({
394 b'type': errtype,
395 b'message': [{b'msg': msg}],
396 }, canonical=True)
406 397
407 398 yield stream.makeframe(requestid=requestid,
408 399 typeid=FRAME_TYPE_ERROR_RESPONSE,
409 flags=flags,
410 payload=msg)
400 flags=0,
401 payload=payload)
411 402
412 403 def createtextoutputframe(stream, requestid, atoms,
413 404 maxframesize=DEFAULT_MAX_FRAME_SIZE):
@@ -664,12 +655,12 b' class serverreactor(object):'
664 655 'framegen': makegen(),
665 656 }
666 657
667 def onapplicationerror(self, stream, requestid, msg):
658 def onservererror(self, stream, requestid, msg):
668 659 ensureserverstream(stream)
669 660
670 661 return 'sendframes', {
671 662 'framegen': createerrorframe(stream, requestid, msg,
672 application=True),
663 errtype='server'),
673 664 }
674 665
675 666 def makeoutputstream(self):
@@ -1051,6 +1042,7 b' class clientreactor(object):'
1051 1042
1052 1043 handlers = {
1053 1044 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe,
1045 FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe,
1054 1046 }
1055 1047
1056 1048 meth = handlers.get(frame.typeid)
@@ -1071,3 +1063,16 b' class clientreactor(object):'
1071 1063 'eos': frame.flags & FLAG_COMMAND_RESPONSE_EOS,
1072 1064 'data': frame.payload,
1073 1065 }
1066
1067 def _onerrorresponseframe(self, request, frame):
1068 request.state = 'errored'
1069 del self._activerequests[request.requestid]
1070
1071 # The payload should be a CBOR map.
1072 m = cbor.loads(frame.payload)
1073
1074 return 'error', {
1075 'request': request,
1076 'type': m['type'],
1077 'message': m['message'],
1078 }
@@ -311,7 +311,7 b' def _httpv2runcommand(ui, repo, req, res'
311 311 command['requestid'],
312 312 encoded)
313 313 else:
314 action, meta = reactor.onapplicationerror(
314 action, meta = reactor.onservererror(
315 315 _('unhandled response type from wire proto command'))
316 316
317 317 if action == 'sendframes':
@@ -373,16 +373,18 b' class ServerReactorTests(unittest.TestCa'
373 373 b'1 2 0 command-response eos %s' % second,
374 374 ])
375 375
376 def testapplicationerror(self):
376 def testservererror(self):
377 377 reactor = makereactor()
378 378 instream = framing.stream(1)
379 379 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
380 380
381 381 outstream = reactor.makeoutputstream()
382 result = reactor.onapplicationerror(outstream, 1, b'some message')
382 result = reactor.onservererror(outstream, 1, b'some message')
383 383 self.assertaction(result, b'sendframes')
384 384 self.assertframesequal(result[1][b'framegen'], [
385 b'1 2 stream-begin error-response application some message',
385 b"1 2 stream-begin error-response 0 "
386 b"cbor:{b'type': b'server', "
387 b"b'message': [{b'msg': b'some message'}]}",
386 388 ])
387 389
388 390 def test1commanddeferresponse(self):
General Comments 0
You need to be logged in to leave comments. Login now