Description
For Java, we have a test case that tries to mimic an exception in the middle of the stream. The full response payload should be "The rain in Spain stays mainly on the plain!"
with each word as it's own response. The Cancelled
exception would come after the Spain
response.
@Test
public void testHttpJson_serverError_receiveErrorAfterLastWordInStream() {
String content = "The rain in Spain";
Status cancelledStatus =
Status.newBuilder().setCode(StatusCode.Code.CANCELLED.ordinal()).build();
ServerStream<EchoResponse> responseStream =
httpjsonClient
.expandCallable()
.call(ExpandRequest.newBuilder().setContent(content).setError(cancelledStatus).build());
Iterator<EchoResponse> echoResponseIterator = responseStream.iterator();
assertThat(echoResponseIterator.next().getContent()).isEqualTo("The");
assertThat(echoResponseIterator.next().getContent()).isEqualTo("rain");
assertThat(echoResponseIterator.next().getContent()).isEqualTo("in");
assertThat(echoResponseIterator.next().getContent()).isEqualTo("Spain");
CancelledException cancelledException =
assertThrows(CancelledException.class, echoResponseIterator::next);
assertThat(cancelledException.getStatusCode().getCode()).isEqualTo(StatusCode.Code.CANCELLED);
}
Error:
...
Caused by: com.google.api.gax.httpjson.HttpJsonStatusRuntimeException: Exception in message delivery
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:316)
... 54 more
Caused by: com.google.api.gax.httpjson.RestSerializationException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 12 column 26 path $[3].severity
at com.google.api.gax.httpjson.ProtoMessageJsonStreamIterator.next(ProtoMessageJsonStreamIterator.java:131)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.consumeMessageFromStream(HttpJsonClientCallImpl.java:362)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:311)
... 54 more
Caused by: com.google.gson.stream.MalformedJsonException: Unterminated object at line 12 column 26 path $[3].severity
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1659)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:500)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:433)
at com.google.api.gax.httpjson.ProtoMessageJsonStreamIterator.next(ProtoMessageJsonStreamIterator.java:82)
... 56 more
which seems to stem from the response coming back as:
[{
"content": "The",
"severity": "UNNECESSARY"
},{
"content": "rain",
"severity": "UNNECESSARY"
},{
"content": "in",
"severity": "UNNECESSARY"
},{
"content": "Spain",
"severity": "UNNECESSARY"
}{"error":{"code":499,"message":"","details":[],"Body":"","Header":null,"Errors":null}}]
The exception above seems to be complaining that there is a missing ,
between the payload and the error message, which I believe is caused from:
EchoService impl:
- Streaming constructing the array:
- Error response:
A few questions:
Would an exception that comes back in the middle of stream come back as a json response? Or would we have an expectation that the trailer message would have an exception with Status Code 499? I see from the local debugging that the status code currently comes back as a 200 (which I believe is due to https://cs.opensource.google/go/go/+/refs/tags/go1.17.1:src/net/http/server.go;l=120-126)
What should the correct behavior be?