Skip to content

Commit 6b34553

Browse files
committed
Detect manual handling of the response by returning the response itself
1 parent 77f71b2 commit 6b34553

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

src/driver/express/ExpressDriver.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class ExpressDriver extends BaseDriver {
105105
const action: Action = { request, response, next };
106106
try {
107107
const checkResult = this.authorizationChecker(action, actionMetadata.authorizedRoles);
108-
108+
109109
const handleError = (result: any) => {
110110
if (!result) {
111111
let error = actionMetadata.authorizedRoles.length === 0 ? new AuthorizationRequiredError(action) : new AccessDeniedError(action);
@@ -114,7 +114,7 @@ export class ExpressDriver extends BaseDriver {
114114
next();
115115
}
116116
};
117-
117+
118118
if (isPromiseLike(checkResult)) {
119119
checkResult
120120
.then(result => handleError(result))
@@ -230,6 +230,12 @@ export class ExpressDriver extends BaseDriver {
230230
*/
231231
handleSuccess(result: any, action: ActionMetadata, options: Action): void {
232232

233+
// if the action returned the response object itself, short-circuits
234+
if (result && result === options.response) {
235+
options.next();
236+
return;
237+
}
238+
233239
// transform result if needed
234240
result = this.transformResult(result, action, options);
235241

src/driver/koa/KoaDriver.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class KoaDriver extends BaseDriver {
8181
const checkResult = actionMetadata.authorizedRoles instanceof Function ?
8282
getFromContainer<RoleChecker>(actionMetadata.authorizedRoles).check(action) :
8383
this.authorizationChecker(action, actionMetadata.authorizedRoles);
84-
84+
8585
const handleError = (result: any) => {
8686
if (!result) {
8787
let error = actionMetadata.authorizedRoles.length === 0 ? new AuthorizationRequiredError(action) : new AccessDeniedError(action);
@@ -90,7 +90,7 @@ export class KoaDriver extends BaseDriver {
9090
return next();
9191
}
9292
};
93-
93+
9494
if (isPromiseLike(checkResult)) {
9595
return checkResult
9696
.then(result => handleError(result))
@@ -213,6 +213,12 @@ export class KoaDriver extends BaseDriver {
213213
*/
214214
handleSuccess(result: any, action: ActionMetadata, options: Action): void {
215215

216+
// if the action returned the context or the response object itself, short-circuits
217+
if (result && (result === options.response || result === options.context)) {
218+
options.next();
219+
return;
220+
}
221+
216222
// transform result if needed
217223
result = this.transformResult(result, action, options);
218224

@@ -227,7 +233,7 @@ export class KoaDriver extends BaseDriver {
227233
} else if (action.successHttpCode) {
228234
options.response.status = action.successHttpCode;
229235
}
230-
236+
231237
if (action.redirect) { // if redirect is set then do it
232238
if (typeof result === "string") {
233239
options.response.redirect(result);
@@ -238,7 +244,7 @@ export class KoaDriver extends BaseDriver {
238244
}
239245
} else if (action.renderedTemplate) { // if template is set then render it // TODO: not working in koa
240246
const renderOptions = result && result instanceof Object ? result : {};
241-
247+
242248
this.koa.use(async function (ctx: any, next: any) {
243249
await ctx.render(action.renderedTemplate, renderOptions);
244250
});
@@ -275,7 +281,7 @@ export class KoaDriver extends BaseDriver {
275281
options.response.body = result;
276282
}
277283
}
278-
284+
279285
// apply http headers
280286
Object.keys(action.headers).forEach(name => {
281287
options.response.set(name, action.headers[name]);

test/functional/action-params.spec.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,22 +89,24 @@ describe("action parameters", () => {
8989
return "<html><body>hello</body></html>";
9090
}
9191

92-
@Get("/users/direct")
93-
getUsersDirectExpress(@Res() response: any): any {
92+
@Get("/users-direct")
93+
getUsersDirect(@Res() response: any): any {
9494
if (typeof response.send === "function")
95-
response.status(201).contentType("custom/x-sample").send("hi, I was written directly to the response");
95+
return response.status(201).contentType("custom/x-sample").send("hi, I was written directly to the response");
9696
else {
9797
response.status = 201;
98-
response.type = "custom/x-sample";
98+
response.type = "custom/x-sample; charset=utf-8";
9999
response.body = "hi, I was written directly to the response";
100+
return response;
100101
}
101102
}
102103

103-
@Get("/users/direct/ctx")
104+
@Get("/users-direct/ctx")
104105
getUsersDirectKoa(@Ctx() ctx: any): any {
105106
ctx.response.status = 201;
106-
ctx.response.type = "custom/x-sample";
107+
ctx.response.type = "custom/x-sample; charset=utf-8";
107108
ctx.response.body = "hi, I was written directly to the response using Koa Ctx";
109+
return ctx;
108110
}
109111

110112
@Get("/users/:userId")
@@ -366,15 +368,15 @@ describe("action parameters", () => {
366368
});
367369

368370
describe("writing directly to the response using @Res should work", () => {
369-
assertRequest([3001, 3002], "get", "users/direct", response => {
371+
assertRequest([3001, 3002], "get", "users-direct", response => {
370372
expect(response).to.be.status(201);
371373
expect(response.body).to.be.equal("hi, I was written directly to the response");
372374
expect(response).to.have.header("content-type", "custom/x-sample; charset=utf-8");
373375
});
374376
});
375377

376378
describe("writing directly to the response using @Ctx should work", () => {
377-
assertRequest([3002], "get", "users/direct/ctx", response => {
379+
assertRequest([3002], "get", "users-direct/ctx", response => {
378380
expect(response).to.be.status(201);
379381
expect(response.body).to.be.equal("hi, I was written directly to the response using Koa Ctx");
380382
expect(response).to.have.header("content-type", "custom/x-sample; charset=utf-8");

0 commit comments

Comments
 (0)