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 native req/res methods #747

Closed
wants to merge 4 commits into from

Conversation

privatenumber
Copy link

This PR contains a:

  • bugfix
  • new feature
  • code refactor
  • test update
  • typo fix
  • metadata update

Motivation / Use-Case

The code was using express specific methods for very simple things (eg. getting/setting header).

I use connect to keep my server light-weight, and others may be using frameworks like koa.

This change refactors the express method calls to use native Node.js HTTP request/response methods instead.

Breaking Changes

Additional Info

@codecov
Copy link

codecov bot commented Oct 27, 2020

Codecov Report

Merging #747 into master will increase coverage by 0.01%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #747      +/-   ##
==========================================
+ Coverage   99.15%   99.16%   +0.01%     
==========================================
  Files          10       10              
  Lines         236      239       +3     
  Branches       72       73       +1     
==========================================
+ Hits          234      237       +3     
  Misses          2        2              
Impacted Files Coverage Δ
src/middleware.js 100.00% <100.00%> (ø)
src/utils/handleRangeHeaders.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9230c13...69a740a. Read the comment docs.

Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

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

We need to setup tests for connect in this case, we can't just change code because something use it, it can breaking other compatibles

@alexander-akait
Copy link
Member

I can help you with it, should be not hard

@ylemkimon
Copy link

Note this is a revert of #726.

@alexander-akait
Copy link
Member

Yes, so I ask to add tests and we should create compatibility.js file and store these hacks there

@privatenumber
Copy link
Author

I can wrap the entire middleware.test.js with an iteration so they all run for express and connect, but this might add a lot of time to tests because it's a very large test file.

What do you think of just swapping express with connect in the test environment?

Since connect is just a middleware framework and doesn't add custom request/response methods like express does, using the underlying native HTTP request/response methods and testing with connect will also mean it works for express. (middlewares designed for connect can always be used by express, eg. compression).

@alexander-akait
Copy link
Member

What do you think of just swapping express with connect in the test environment?

Bad idea, we should we should test on what it works on

Since connect is just a middleware framework and doesn't add custom request/response methods like express does, using the underlying native HTTP request/response methods and testing with connect will also mean it works for express. (middlewares designed for connect can always be used by express, eg. compression).

yes, but we need to add it for all tests, otherwise we can't guarantee compatibility

@privatenumber
Copy link
Author

How would you like to add tests for both? (eg. should I wrap the entire middleware tests so they run for both express and connect?)

Also, supporting connect is effectively supporting a vanilla Node.js HTTP server as well, if you're interested in adding tests for that as well.

@alexander-akait
Copy link
Member

How would you like to add tests for both? (eg. should I wrap the entire middleware tests so they run for both express and connect?)

Ideally - yes

Also, supporting connect is effectively supporting a vanilla Node.js HTTP server as well, if you're interested in adding tests for that as well.

Yes 👍

@privatenumber
Copy link
Author

privatenumber commented Oct 29, 2020

@evilebottnawi

I added an outer iteration in the middleware test so that they're executed for connect and express. There's a few tests that fail though, but only when I run them both. If I comment out either connect or express they all succeed.

I couldn't find out what was causing this. Do you mind looking into this?

Also looked into adding a vanilla HTTP server, but I may have over-spoke. Adding middleware support wasn't as easy as I imagined... the whole connect module is doing that after all, so probably not necessary anyway.

BTW I still think it's kinda pointless to test for express if we're testing with connect, and we're not using any express features. At most, I think just add a smaller express smoke test. Maybe you'll agree as you checkout the code.

@privatenumber privatenumber mentioned this pull request Oct 29, 2020
6 tasks
@ylemkimon
Copy link

BTW I still think it's kinda pointless to test for express if we're testing with connect, and we're not using any express features. At most, I think just add a smaller express smoke test. Maybe you'll agree as you checkout the code.

webpack-dev-server uses express for the framework.

@privatenumber
Copy link
Author

privatenumber commented Oct 29, 2020

Thanks for chiming in @ylemkimon

This PR removes dependency on express-only API so that it can be HTTP framework agnostic. Instead of using the express API, this middleware now only uses native Node.js HTTP API. Therefore, this middleware now works with any HTTP framework that expose native request/response instances because we're no longer interacting with any framework code. The only dependency now is the "HTTP middleware paradigm".

You can confirm this by swapping express with connect in the tests. They will all pass because the code is now framework agnostic.

connect is just the "middleware" feature of express, and because of its minimal approach, it makes it easier to test and keep a stricter scope. For example, express automatically adds etags, which interferes with testing the etag feature that I'm working on here.

So, testing with express in addition to connect is almost like, making a module that interacts with the DOM, and testing it with Preact and React via mounted hook... as long as it's interacting with the DOM, it's going to work so you don't need to test it with every JS framework out there.

To support this even further, just take a look at one of the most popular express middleware compression by the express team. It doesn't even use express or connect to test, it just uses a simple HTTP server.

If we want first-class support for express just in case, I think adding a smoke test for it will be sufficient.

res.setHeader(
'Content-Type',
contentType || 'application/octet-stream'
);
Copy link
Member

Choose a reason for hiding this comment

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

We should always use official middleware API, so for example we shoudl use express API, for connect (no example API) we should use http module API, why? Because other middlewares/tools can add additional logic for built-in API, and we will not working properly with them

Copy link
Member

@alexander-akait alexander-akait Oct 29, 2020

Choose a reason for hiding this comment

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

So we need to create compatibility file and put some utils there, like:

function responseGetHeader(response, header) { 
  // Comment there we describe what it function belong express API and some more interesting stuff
  if (response.get(header)) {
    // Logic
  }

  // Other logic
}

Copy link
Author

Choose a reason for hiding this comment

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

I agree with your explanation, and that's why this middleware can't be used by Koa, even though they expose native request/response.

However, if we scope our support level to vanilla HTTP, express, connect, and other frameworks that don't add extra logic, then we don't need to do that. We can't possibly support all frameworks anyway.

Copy link
Member

Choose a reason for hiding this comment

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

So let's take my suggestion, it is easy and will not confusing for future refactoring

Copy link
Author

Choose a reason for hiding this comment

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

If the support level is strictly express and connect, I think it's unnecessary.

Going back to the case with compression, I'm not convinced why a third-party middleware requires this abstraction when a first-party middleware doesn't.

Copy link
Member

Choose a reason for hiding this comment

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

Can you clarify?

@clarkdo
Copy link

clarkdo commented Oct 29, 2020

Thanks for this pr, look forward to the release.

@privatenumber
Copy link
Author

@evilebottnawi

Following up with #747 (comment)

I couldn't find out what was causing this. Do you mind looking into this?

@alexander-akait
Copy link
Member

Okay, I am start to working on it, want to separate it on two commits - prepare tests + compatibility fixes to avoid dirty git history

@alexander-akait
Copy link
Member

Fixed #760

@privatenumber big thanks for helping and investigating, I will do release tomorrow, the next target - ETag header and maybe other cache headers

@privatenumber
Copy link
Author

Thanks for getting it in @evilebottnawi. Looking forward to being able to use it!

Not a big deal because I primarily did this for the feature, but for future reference, I would appreciate it if my commits could've somehow been integrated into your PR and the repository. I put in a lot of hours into this but I won't be credited as a contributor.

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.

None yet

4 participants