Skip to content

Commit e4b0698

Browse files
committed
After calling the user function, flush either the OutputStream or the Writer as appropriate. Calling getWriter().flush() will fail if getOutputStream() has previously been called. The method ServletResponse.flushBuffer() might be expected to work here but it did not.
Fixes #15. PiperOrigin-RevId: 296899120
1 parent 00f59ac commit e4b0698

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

invoker/core/src/main/java/com/google/cloud/functions/invoker/NewHttpFunctionExecutor.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@ public void service(HttpServletRequest req, HttpServletResponse res) {
7272
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
7373
} finally {
7474
try {
75-
respImpl.getWriter().flush();
75+
// Shouldn't HttpServletResponse.flushBuffer() work here? But it doesn't. So we have to
76+
// flush whichever of getWriter() or getOutputStream() works.
77+
try {
78+
respImpl.getWriter().flush();
79+
} catch (IllegalStateException e) {
80+
respImpl.getOutputStream().flush();
81+
}
7682
} catch (IOException e) {
7783
// Too bad, can't flush.
7884
}

invoker/core/src/test/java/com/google/cloud/functions/invoker/IntegrationTest.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ private static CloudEventImpl<Map<String, Object>> sampleCloudEvent(File snoopFi
112112
.withData(ImmutableMap.of("a", 2, "b", 3, "targetFile", snoopFile.toString()))
113113
.withTime(ZonedDateTime.of(2018, 4, 5, 17, 31, 0, 0, ZoneOffset.UTC))
114114
.build();
115-
116115
}
117116

118117
private static int serverPort;
@@ -146,6 +145,8 @@ abstract static class TestCase {
146145

147146
abstract Optional<String> expectedJsonString();
148147

148+
abstract Optional<String> expectedContentType();
149+
149150
abstract String httpContentType();
150151

151152
abstract ImmutableMap<String, String> httpHeaders();
@@ -175,6 +176,8 @@ abstract static class Builder {
175176

176177
abstract Builder setExpectedResponseText(Optional<String> x);
177178

179+
abstract Builder setExpectedContentType(String x);
180+
178181
abstract Builder setExpectedJsonString(String x);
179182

180183
abstract Builder setHttpContentType(String x);
@@ -238,7 +241,17 @@ public void newEcho() throws Exception {
238241
testHttpFunction(
239242
fullTarget("NewEcho"),
240243
ImmutableList.of(
241-
TestCase.builder().setRequestText(testText).setExpectedResponseText(testText).build()));
244+
TestCase.builder()
245+
.setRequestText(testText)
246+
.setExpectedResponseText(testText)
247+
.setExpectedContentType("text/plain")
248+
.build(),
249+
TestCase.builder()
250+
.setHttpContentType("application/octet-stream")
251+
.setRequestText(testText)
252+
.setExpectedResponseText(testText)
253+
.setExpectedContentType("application/octet-stream")
254+
.build()));
242255
}
243256

244257
@Test
@@ -462,6 +475,8 @@ private void testFunction(
462475
.that(response.getStatus()).isEqualTo(testCase.expectedResponseCode());
463476
testCase.expectedResponseText()
464477
.ifPresent(text -> expect.that(response.getContentAsString()).isEqualTo(text));
478+
testCase.expectedContentType()
479+
.ifPresent(type -> expect.that(response.getMediaType()).isEqualTo(type));
465480
if (testCase.snoopFile().isPresent()) {
466481
checkSnoopFile(testCase.snoopFile().get(), testCase.expectedJsonString().get());
467482
}

invoker/core/src/test/java/com/google/cloud/functions/invoker/testfunctions/NewEcho.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,27 @@
33
import com.google.cloud.functions.HttpFunction;
44
import com.google.cloud.functions.HttpRequest;
55
import com.google.cloud.functions.HttpResponse;
6+
import java.io.InputStream;
7+
import java.io.OutputStream;
68
import java.util.stream.Collectors;
79

810
public class NewEcho implements HttpFunction {
911
@Override
1012
public void service(HttpRequest request, HttpResponse response) throws Exception {
11-
String body = request.getReader().lines().collect(Collectors.joining("\n")) + "\n";
12-
response.setContentType("text/plain");
13-
response.getWriter().write(body);
14-
response.getWriter().flush();
13+
boolean binary = "application/octet-stream".equals(request.getContentType().orElse(null));
14+
if (binary) {
15+
response.setContentType("application/octet-stream");
16+
byte[] buf = new byte[1024];
17+
InputStream in = request.getInputStream();
18+
OutputStream out = response.getOutputStream();
19+
int n;
20+
while ((n = in.read(buf)) > 0) {
21+
out.write(buf, 0, n);
22+
}
23+
} else {
24+
String body = request.getReader().lines().collect(Collectors.joining("\n")) + "\n";
25+
response.setContentType("text/plain");
26+
response.getWriter().write(body);
27+
}
1528
}
1629
}

0 commit comments

Comments
 (0)