fix: release upstream response body before sending error on status/header failure#27
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughCancel the upstream response body in Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
…ader failure Body cancellation on okStatus and okHeaders failures is fire-and-forget — no need to await before calling sendError, which avoids adding latency to the error response path while still releasing the connection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5f23f82 to
37a2b75
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/ThumbnailApi.ts (1)
99-113: Consider deduplicating body-cancel logic into a small helper.Same cleanup snippet appears in two branches; extracting it reduces drift risk if this behavior changes later.
♻️ Optional refactor
+ const releaseUpstreamBody = (response: Response): void => { + void response.body?.cancel?.().catch(() => {}); + }; + if (!this.responseHelper.okStatus(status)) { const error = new Error(`Status ${String(status)} from upstream.`); - remoteImageResponse.body?.cancel?.().catch(() => {}); + releaseUpstreamBody(remoteImageResponse); this.sendError(expressResponse, itemId, 404, error); return; } @@ if (!this.responseHelper.okHeaders(remoteImageResponse.headers)) { const error = new Error(`Got bad headers from upstream.`); - remoteImageResponse.body?.cancel?.().catch(() => {}); + releaseUpstreamBody(remoteImageResponse); this.sendError(expressResponse, itemId, 404, error); return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ThumbnailApi.ts` around lines 99 - 113, Extract the repeated body cancel-and-ignore-errors snippet into a small helper on ThumbnailApi (e.g., a private method like cancelRemoteBody(remoteImageResponse) or a utility function) and call it from both branches instead of repeating remoteImageResponse.body?.cancel?.().catch(() => {}); update the two places that currently run on failed okStatus and failed okHeaders to invoke this helper before calling this.sendError(expressResponse, itemId, 404, error); keep use of optional chaining and swallow errors in the helper to preserve existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/ThumbnailApi.ts`:
- Around line 99-113: Extract the repeated body cancel-and-ignore-errors snippet
into a small helper on ThumbnailApi (e.g., a private method like
cancelRemoteBody(remoteImageResponse) or a utility function) and call it from
both branches instead of repeating remoteImageResponse.body?.cancel?.().catch(()
=> {}); update the two places that currently run on failed okStatus and failed
okHeaders to invoke this helper before calling this.sendError(expressResponse,
itemId, 404, error); keep use of optional chaining and swallow errors in the
helper to preserve existing behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 92eebe58-652f-43c7-b225-812db75d376a
📒 Files selected for processing (1)
src/ThumbnailApi.ts
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/ThumbnailApi.ts`:
- Around line 174-176: The non-OK S3 response path in serveItemFromS3 currently
throws/returns without releasing the upstream response body; update
serveItemFromS3 to call the centralized releaseUpstreamBody(response) before
exiting on a non-OK status so the response.body is cancelled and pooled
connections are freed; locate the status check in serveItemFromS3 and insert a
call to releaseUpstreamBody(response) (using the existing private
releaseUpstreamBody method) immediately prior to any throw/return on error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 532bcdfc-d75f-4a70-a06e-37de8b61fd01
📒 Files selected for processing (1)
src/ThumbnailApi.ts
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
…ypeError body?.cancel?.() returns undefined when body is null (e.g. a no-body upstream response), and calling .catch() on undefined throws TypeError. Using ?.catch() safely short-circuits to undefined in that case while still suppressing Promise rejections when cancel returns a Promise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/ThumbnailApi.ts (1)
174-176:⚠️ Potential issue | 🟠 MajorHelper is centralized, but one upstream error path still skips it (S3 status failure).
serveItemFromS3still returns on non-OK status without releasing the upstream body (Line 142–145), so pooled connections can remain occupied under load.Suggested fix
if (!this.responseHelper.okStatus(status)) { const error = new Error(`Status ${String(status)} from upstream.`); + this.releaseUpstreamBody(response); this.sendError(expressResponse, itemId, 404, error); return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ThumbnailApi.ts` around lines 174 - 176, serveItemFromS3 currently returns early when the S3 response status is not OK without calling the centralized releaseUpstreamBody helper, which can leave pooled connections occupied; update serveItemFromS3 to call releaseUpstreamBody(response) immediately before any early return on non-OK Response (and in any S3 error/early-exit paths) so response.body is properly cancelled; reference the serveItemFromS3 function and the releaseUpstreamBody(Response) helper when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/ThumbnailApi.ts`:
- Around line 174-176: serveItemFromS3 currently returns early when the S3
response status is not OK without calling the centralized releaseUpstreamBody
helper, which can leave pooled connections occupied; update serveItemFromS3 to
call releaseUpstreamBody(response) immediately before any early return on non-OK
Response (and in any S3 error/early-exit paths) so response.body is properly
cancelled; reference the serveItemFromS3 function and the
releaseUpstreamBody(Response) helper when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 90643b4a-79a2-47f9-92d1-1417f56731d1
📒 Files selected for processing (1)
src/ThumbnailApi.ts
Apply the same releaseUpstreamBody call to the serveItemFromS3 error path that was already added to proxyItemFromContributor, so connections are returned to the pool on S3 upstream failures too. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Summary
okStatusorokHeaderschecks fail, so the connection is released back to the pool even on error pathssendError()on it, and this avoids adding latency to the 404 error responseTest plan
🤖 Generated with Claude Code
Summary
This PR ensures upstream response bodies are explicitly cancelled when status or header validation fail in the image proxy flow so the underlying connection is released back to the pool. A new private helper releaseUpstreamBody(response: Response) is added; it calls response.body?.cancel?.()?.catch(() => {}) and is invoked (fire-and-forget, intentionally not awaited) on failure paths where translated upstream status is not okStatus and where okHeaders validation fails. The S3-serving path's translated-status failure branch was also updated to cancel the upstream response body.
The cancellation is deliberately not awaited to avoid adding latency to error responses (e.g., prompt 404s).
Changes
Impact Assessment
Test Plan
Notes: