Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,8 @@ public void earlyServerClose_noServerHeaders() throws Exception {
Metadata clientStreamTrailers =
clientStreamListener.awaitTrailers(TIMEOUT_MS, TimeUnit.MILLISECONDS);
checkClientStatus(status, clientStreamStatus);
assertEquals(
Lists.newArrayList(trailers.getAll(asciiKey)),
Lists.newArrayList(clientStreamTrailers.getAll(asciiKey)));
assertAsciiMetadataValuesEqual(
trailers.getAll(asciiKey), clientStreamTrailers.getAll(asciiKey));
assertEquals(
Lists.newArrayList(trailers.getAll(binaryKey)),
Lists.newArrayList(clientStreamTrailers.getAll(binaryKey)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,10 @@ public void deadlineExceeded() throws Exception {
Pattern.matches("CallOptions deadline exceeded after .*s. \\[.*\\]", desc)
// If server expires first, it'd reset the stream and client would generate a different
// message
|| desc.startsWith("ClientCall was cancelled at or after deadline."));
|| desc.startsWith("ClientCall was cancelled at or after deadline.")
// If server expires first and sends the status instead of resetting the stream (e.g.,
// servlet based servers), the client sees the server's status
|| desc.equals("context timed out"));
}

assertStatsTrace("grpc.testing.TestService/EmptyCall", Status.Code.OK);
Expand Down
12 changes: 8 additions & 4 deletions servlet/src/main/java/io/grpc/servlet/ServletServerStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,15 @@ public void writeTrailers(Metadata trailers, boolean headersSent, Status status)
new Object[] {logId, trailers, headersSent, status});
}
if (!headersSent) {
writeHeadersToServletResponse(trailers);
} else {
serializeHeaders(trailers,
(k, v) -> trailerSupplier.get().merge(k, v, (oldV, newV) -> oldV + "," + newV));
// Don't send a Trailers-Only response (status in the response headers). Some containers,
// like Tomcat, don't set END_STREAM on that HEADERS frame and instead terminate the stream
// with an empty DATA frame, which the client treats as a protocol error, discarding the
// status. Send (empty) headers followed by real trailers instead.
writeHeadersToServletResponse(new Metadata());
resp.setTrailerFields(trailerSupplier);
}
serializeHeaders(trailers,
(k, v) -> trailerSupplier.get().merge(k, v, (oldV, newV) -> oldV + "," + newV));

writer.complete();
}
Expand Down
25 changes: 0 additions & 25 deletions servlet/src/tomcatTest/java/io/grpc/servlet/TomcatInteropTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,29 +112,4 @@ protected boolean metricsExpected() {
@Ignore("Tomcat is broken on client GOAWAY")
@Test
public void gracefulShutdown() {}

@Override
@Ignore("Tomcat is not able to send trailer only")
@Test
public void specialStatusMessage() {}

@Override
@Ignore("Tomcat is not able to send trailer only")
@Test
public void unimplementedMethod() {}

@Override
@Ignore("Tomcat is not able to send trailer only")
@Test
public void statusCodeAndMessage() {}

@Override
@Ignore("Tomcat is not able to send trailer only")
@Test
public void emptyStream() {}

@Override
@Ignore("Tomcat is not able to send trailer only")
@Test
public void timeoutOnSleepingServer() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,21 +261,6 @@ public void interactionsAfterClientStreamCancelAreNoops() {}
@Test
public void clientCancel() {}

@Override
@Ignore("Tomcat does not support trailers only")
@Test
public void earlyServerClose_noServerHeaders() {}

@Override
@Ignore("Tomcat does not support trailers only")
@Test
public void earlyServerClose_serverFailure() {}

@Override
@Ignore("Tomcat does not support trailers only")
@Test
public void earlyServerClose_serverFailure_withClientCancelOnListenerClosed() {}

@Override
@Ignore("regression since bumping grpc v1.46 to v1.53")
@Test
Expand Down
Loading