Skip to content

Commit 2f76013

Browse files
committed
Fix bug where sse response hangs if handler threw an error.
1 parent edafd9a commit 2f76013

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

spec/helper.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ export function runHandler(
4747
// MockResponse mocks an express.Response.
4848
// This class lives here so it can reference resolve and reject.
4949
class MockResponse {
50-
private sentBody = "";
50+
private sentBody: string | undefined;
5151
private statusCode = 0;
5252
private headers: { [name: string]: string } = {};
5353
private callback: () => void;
54+
private writeCalled = false;
5455

5556
constructor() {
5657
request.on("close", () => this.end());
@@ -71,29 +72,42 @@ export function runHandler(
7172
}
7273

7374
public send(sendBody: any) {
74-
const toSend = typeof sendBody === "object" ? JSON.stringify(sendBody) : sendBody;
75-
const body = this.sentBody ? this.sentBody + ((toSend as string) || "") : toSend;
76-
77-
resolve({
78-
status: this.statusCode,
79-
headers: this.headers,
80-
body,
81-
});
82-
if (this.callback) {
83-
this.callback();
75+
if (this.writeCalled) {
76+
throw Error("Cannot set headers after they are sent to the client")
8477
}
78+
79+
const toSend = typeof sendBody === "object" ? JSON.stringify(sendBody) : sendBody;
80+
const body = typeof this.sentBody === 'undefined' ? toSend : this.sentBody + ((toSend as string) || "");
81+
this.end(body);
8582
}
8683

8784
public write(writeBody: any, cb?: () => void) {
88-
this.sentBody += typeof writeBody === "object" ? JSON.stringify(writeBody) : writeBody;
85+
this.writeCalled = true;
86+
87+
if (typeof this.sentBody === 'undefined') {
88+
this.sentBody = writeBody;
89+
} else {
90+
this.sentBody += typeof writeBody === "object" ? JSON.stringify(writeBody) : writeBody;
91+
}
8992
if (cb) {
9093
setImmediate(cb);
9194
}
9295
return true;
9396
}
9497

95-
public end() {
96-
this.send(undefined);
98+
public end(body?: unknown) {
99+
if (body) {
100+
this.write(body);
101+
}
102+
resolve({
103+
status: this.statusCode,
104+
headers: this.headers,
105+
body: this.sentBody,
106+
});
107+
108+
if (this.callback) {
109+
this.callback();
110+
}
97111
}
98112

99113
public on(event: string, callback: () => void) {

src/common/providers/https.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,8 @@ function wrapOnCallHandler<Req = any, Res = any, Stream = unknown>(
933933
const { status } = httpErr.httpErrorCode;
934934
const body = { error: httpErr.toJSON() };
935935
if (version === "gcfv2" && req.header("accept") === "text/event-stream") {
936-
res.send(encodeSSE(body));
936+
res.write(encodeSSE(body));
937+
res.end();
937938
} else {
938939
res.status(status).send(body);
939940
}

0 commit comments

Comments
 (0)