Skip to content

HttpJson ServerSideStreaming error in EchoClient #1286

Open
@lqiu96

Description

@lqiu96

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:

func (s *echoServerImpl) Expand(in *pb.ExpandRequest, stream pb.Echo_ExpandServer) error {

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions