Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use base node http types #721

Closed
wants to merge 5 commits into from

Conversation

cdaringe
Copy link

@cdaringe cdaringe commented Feb 27, 2022

Description

  • Refactor http-proxy-middleware middeware types to be properly x-server compatible, from both a typescript & node.js lens
  • Augment http.IncomingMessage with http-proxy-middleware values permissible on req, but not present by default

BREAKING CHANGE: RequestHandler => RequestMiddleware. Middleware now
is expressed in terms of node core http.* types, which express req/res
are compatible with. Orienting to base http.* types allows better typing
across all node servers, as eventually each implementation has these
values in their servers. That is to say, express, koa, fastify, next,
etc all use http.IncomingMessage/http.ServerResponse under the hood,
thus the new middleware types are compatible with everyone.

Technically this should be backwards compatible for most users. However, exotic coupling to the previous types (e.g. Parameters<typeof createProxyMiddleware> could induce subtle breakages.

Motivation and Context

See #719

How has this been tested?

  • Mo' tests added!

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

BREAKING CHANGE: `RequestHandler` => `RequestMiddleware`. Middleware now
is expressed in terms of node core http.* types, which express req/res
are compatible with. Orienting to base http.* types allows better typing
accross all node servers, as eventually each implementation has these
values in their servers. That is to say, express, koa, fastify, next,
etc all use http.IncomingMessage/http.ServerResponse under the hood,
thus the new middleware types are compatible with everyone.
@@ -5,8 +5,8 @@ import * as querystring from 'querystring';
/**
* Fix proxied body if bodyParser is involved.
*/
export function fixRequestBody(proxyReq: http.ClientRequest, req: http.IncomingMessage): void {
const requestBody = (req as Request).body;
Copy link
Author

Choose a reason for hiding this comment

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

cast no longer required. augment handles this

BREAKING CHANGE: `RequestHandler` => `RequestMiddleware`. Middleware now
is expressed in terms of node core http.* types, which express req/res
are compatible with. Orienting to base http.* types allows better typing
accross all node servers, as eventually each implementation has these
values in their servers. That is to say, express, koa, fastify, next,
etc all use http.IncomingMessage/http.ServerResponse under the hood,
thus the new middleware types are compatible with everyone.
package.json Show resolved Hide resolved
src/types.ts Show resolved Hide resolved
next: Next
) => unknown | Promise<unknown>;

export type RequestMiddleware = RequestMiddlewareFunction & {
Copy link
Author

Choose a reason for hiding this comment

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

and here's the 2nd most significant change 👀

@chimurai
Copy link
Owner

chimurai commented Feb 27, 2022

Thanks for taking a shot at improving the Types. 🙏

Really like the improvements you've made so far.
Looks like your changes are tackling the majority of the typing issues. (as listed in #720)

Could you change the base branch of this PR to v3?
(https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request)

Was already working on some improvements (breaking changes) to free up some legacy code which was preventing future improvements.

Timing is a bit unfortunate. Hopefully it won't create too many conflicts with this PR. 🤞

I'll start reviewing (manually as well) when the base branch is changed to v3.

@chimurai chimurai added this to the v3.0.0 milestone Feb 27, 2022
req: http.IncomingMessage,
res: http.ServerResponse,
next: Next
) => unknown | Promise<unknown>;

Choose a reason for hiding this comment

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

Given that this function is using a callback, should it instead be => void | Promise<void>?

Copy link
Author

@cdaringe cdaringe Mar 3, 2022

Choose a reason for hiding this comment

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

we could, but I'd suggest that such a type may be less portable. it would force all middleware providers to actually have void return types. i think they generally are void (connect, express, koa), which makes such a suggestion quite reasonable. however, unknown doesn't hurt--as those middleware consumers aren't ever going to consume those values. for middlewares that do return a value, using void means they wouldn't be able to use http-proxy-middleware typed, and i'd like to err on the side of supporting any such users

Copy link
Author

@cdaringe cdaringe Mar 3, 2022

Choose a reason for hiding this comment

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

in other words, if marcs-cool-server used a middleware type of (req,res,next) => res, we'd be in trouble. at the office, i have some cohorts who were quite passionate about res returning middleware, which i didn't necessarily agree with. but know that such impls do exist out there in userspace. perhaps not by the big players.

}

export type Next = (...args: unknown[]) => unknown;

Choose a reason for hiding this comment

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

Suggested change
export type Next = (...args: unknown[]) => unknown;
export type Next = (err?: any) => void;

To match https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express-serve-static-core/index.d.ts#L34

Copy link
Author

@cdaringe cdaringe Mar 3, 2022

Choose a reason for hiding this comment

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

that's an express specific API, which this PR is intentionally trying to decouple from. using that type would assert that param0 is always an optional err in other servers' next interfaces, which may not be the case. for max x-server compat, i'd opt to not offer such a coupled interface, but perhaps allow a user to extend somehow.

i have to refactor this for the v3 branch, i'll think more on it shortly

@cdaringe cdaringe mentioned this pull request Mar 3, 2022
5 tasks
@cdaringe
Copy link
Author

cdaringe commented Mar 3, 2022

moved to #723

@cdaringe cdaringe closed this Mar 3, 2022
@chimurai chimurai removed this from the v3.0.0 milestone Mar 19, 2022
@chimurai chimurai mentioned this pull request Feb 22, 2023
5 tasks
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.

3 participants