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 |
|
|
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: |
|
|
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, |
|
|
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= |
|
|
410 |
payload= |
|
|
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 on |
|
|
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 |
|
|
|
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.on |
|
|
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 test |
|
|
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.on |
|
|
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 |
|
|
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