Skip to content

fix(types): allow Promise<void> return type for proxyRes callback#1190

Merged
chimurai merged 1 commit intochimurai:masterfrom
cyphercodes:master
Apr 5, 2026
Merged

fix(types): allow Promise<void> return type for proxyRes callback#1190
chimurai merged 1 commit intochimurai:masterfrom
cyphercodes:master

Conversation

@cyphercodes
Copy link
Copy Markdown
Contributor

@cyphercodes cyphercodes commented Apr 5, 2026

Fixes #1151

Problem

The proxyRes callback type only allowed void return type, but when using responseInterceptor, the handler is async and returns Promise.

Solution

Updated the proxyRes type to allow both void and Promise return types.

Changes

  • Changed proxyRes callback return type from void to void | Promise

Summary by CodeRabbit

Release Notes

  • New Features
    • Proxy response callbacks now support both synchronous and asynchronous operations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9e804821-8b5b-4506-869d-fb6a84a03f2e

📥 Commits

Reviewing files that changed from the base of the PR and between 6911434 and f399984.

📒 Files selected for processing (1)
  • src/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/types.ts

📝 Walkthrough

Walkthrough

The proxyRes callback handler type in the OnProxyEvent interface was updated to support asynchronous operations by changing its return type from void to void | Promise<void>, enabling both synchronous and promise-based implementations.

Changes

Cohort / File(s) Summary
Type Definition Update
src/types.ts
Updated proxyRes handler return type in OnProxyEvent interface from void to void | Promise<void> to support async callbacks.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

🐰 A rabbit hops with joy today,
Async callbacks come out to play,
Promises now flow through the way,
No more stuck on sync's old bay,
Types evolve, we hop and sway! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: allowing Promise return type for the proxyRes callback to match actual async handler usage.
Linked Issues check ✅ Passed The code change directly addresses issue #1151 by updating the proxyRes callback return type from void to void | Promise, aligning the type declaration with async responseInterceptor handlers.
Out of Scope Changes check ✅ Passed The pull request contains only a single, focused type change to the proxyRes callback signature that directly resolves the linked issue; no out-of-scope changes are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/types.ts`:
- Line 51: The proxyRes type allows async handlers but the event registration
currently casts them to (...args: unknown[]) => void so Promise rejections are
dropped; fix the registration in the proxy-events module by removing the void
cast and invoking handlers via Promise.resolve(handler(...args)).catch(err => /*
log/forward the error */), or by making the registration function async and
awaiting handler(...args) inside a try/catch; ensure any call sites that
register proxyRes handlers preserve the original signature so Promise<void>
rejections are logged/handled rather than ignored.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f209248-a19a-4777-9e13-492a6fce577c

📥 Commits

Reviewing files that changed from the base of the PR and between 3e7d6df and 6911434.

📒 Files selected for processing (1)
  • src/types.ts

Comment thread src/types.ts
head: any,
) => void;
proxyRes?: (proxyRes: TReq, req: TReq, res: TRes) => void;
proxyRes?: (proxyRes: TReq, req: TReq, res: TRes) => void | Promise<void>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that async `options.on` handlers are currently registered without await/catch handling.
set -euo pipefail

# Inspect current event registration implementation
sed -n '1,140p' src/plugins/default/proxy-events.ts

# Show exact registration line and nearby context
rg -n -C3 "proxyServer\\.on<keyof typeof options\\.on>\\(eventName, handler as \\(\\.\\.\\.args: unknown\\[\\]\\) => void\\)" src/plugins/default/proxy-events.ts

# Check whether there is any Promise normalization/catch around handler invocation
rg -n -C2 "Promise\\.resolve\\(|\\.catch\\(|await .*handler" src/plugins/default/proxy-events.ts

Repository: chimurai/http-proxy-middleware

Length of output: 1734


🏁 Script executed:

# Extract the OnProxyEvent type definition around line 51
sed -n '40,65p' src/types.ts

Repository: chimurai/http-proxy-middleware

Length of output: 965


🏁 Script executed:

# Check if response-interceptor.ts relates to proxyRes events
rg -n "proxyRes|response-interceptor" src/handlers/response-interceptor.ts | head -20

# Check if any other event handlers wrap Promises in their registration
rg -n -B3 -A3 "Promise.*handler|catch.*handler|\.then(" src/plugins/default/proxy-events.ts

# Search broader for Promise handling patterns in proxy server event registration
rg -n "\.on\(" src/plugins/default/proxy-events.ts

Repository: chimurai/http-proxy-middleware

Length of output: 935


🏁 Script executed:

# Search for where responseInterceptor is used/imported
rg -n "responseInterceptor|response-interceptor" --type ts | grep -v node_modules

# Search for how it relates to on.proxyRes
rg -n "on\.proxyRes|options\.on\.proxyRes" src/

Repository: chimurai/http-proxy-middleware

Length of output: 1916


🏁 Script executed:

# Get the full responseInterceptor implementation to see if it handles Promise rejections
sed -n '23,100p' src/handlers/response-interceptor.ts

Repository: chimurai/http-proxy-middleware

Length of output: 2557


proxyRes permits async handlers, but Promise rejections are silently dropped at runtime.

Line 51 correctly widens the type to void | Promise<void>, but handler registration at src/plugins/default/proxy-events.ts:42 still casts handlers to (...args: unknown[]) => void, causing any Promise rejections to be unhandled. This affects both direct async handlers and even utility wrappers like responseInterceptor that return Promise<void>, since both are registered without Promise handling.

💡 Suggested runtime guard in event registration
-      proxyServer.on<keyof typeof options.on>(eventName, handler as (...args: unknown[]) => void);
+      proxyServer.on<keyof typeof options.on>(eventName, (...args: unknown[]) => {
+        try {
+          const result = (handler as (...a: unknown[]) => unknown)(...args);
+          if (result && typeof (result as Promise<unknown>).then === 'function') {
+            void (result as Promise<unknown>).catch((error) => {
+              debug(`event handler "${String(eventName)}" rejected: %o`, error);
+            });
+          }
+        } catch (error) {
+          debug(`event handler "${String(eventName)}" threw: %o`, error);
+        }
+      });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/types.ts` at line 51, The proxyRes type allows async handlers but the
event registration currently casts them to (...args: unknown[]) => void so
Promise rejections are dropped; fix the registration in the proxy-events module
by removing the void cast and invoking handlers via
Promise.resolve(handler(...args)).catch(err => /* log/forward the error */), or
by making the registration function async and awaiting handler(...args) inside a
try/catch; ensure any call sites that register proxyRes handlers preserve the
original signature so Promise<void> rejections are logged/handled rather than
ignored.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 5, 2026

Coverage Status

coverage: 94.012%. remained the same
when pulling f399984 on cyphercodes:master
into 87107bf on chimurai:master.

The proxyRes callback type only allowed void return type, but when
using responseInterceptor, the handler is async and returns Promise<void>.

This fix updates the type to allow both void and Promise<void> return
types, matching the actual behavior of responseInterceptor.

Fixes chimurai#1151
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 5, 2026

npm i https://pkg.pr.new/http-proxy-middleware@1190

commit: f399984

@chimurai chimurai merged commit 3945773 into chimurai:master Apr 5, 2026
12 checks passed
@chimurai
Copy link
Copy Markdown
Owner

chimurai commented Apr 5, 2026

Thanks!

@chimurai chimurai added this to the v4 milestone Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong type of ProxyResCallback (void instead of Promise<void>)

3 participants