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

fix: check existence of res.getHeader and set the correct Content-Type #385

Merged

Conversation

ulivz
Copy link
Contributor

@ulivz ulivz commented Mar 24, 2019

What kind of change does this PR introduce?

Bug fix

Did you add tests for your changes?

No tests needed.

Summary

This PR is tagged "bug fix" but actually a feature request.

I'm the maintainer of VuePress and recently we found a very influential issue(vuepress dev: throws res.getHeader() is not a function) but we cannot fix it by ourself. and it's introduced by b2a6fed. (But after careful investigation, I found that this is the legacy of history.)

This is due to VuePress@0.x depends on webpack-serve@1.0.2, webpack-serve depends on koa-webpack, and koa-webpack doesn't lock the version of webpack-dev-middleware:

https://github.com/shellscape/koa-webpack/blob/0ea07dbd11f899f0e419808f2472b2d832d0d9c3/package.json#L24

"webpack-dev-middleware": "^3.0.0",

The issue is already fixed in shellscape/koa-webpack#110 (released as v5.2.2) but we cannot enjoy this fix since webpack-serve@1.0.2 depends on koa-webpack@4.x.

One way to resolve the issue is to update webpack-serve dependency to 2.x.
However, webpack-serve introduced breaking changes in v2 and we‘re not going to make any technological changes for VuePress@0.x because it's stable enough and we're also focused on 1.x.

Since webpack-serve has been deprecated, the best way I can think of is to check the existence of res.getHeader at webpack-dev-middleware. Of course, all of this is because the author of koa-webpack did not pass in the getHeader method in 4.x at that time:

https://github.com/shellscape/koa-webpack/blob/v4.0.0/index.js#L48

  return (context, next) => Promise.all([
    waitMiddleware(),
    new Promise((resolve) => {
      dev(context.req, {
        end: (content) => {
          context.body = content; // eslint-disable-line no-param-reassign
          resolve();
        },
        setHeader: context.set.bind(context),
        locals: context.state
      }, () => resolve(next()));
    })
  ]);

I'll appreciate you if you accept this change, Thanks!

Does this PR introduce a breaking change?

No.

Other information

@jsf-clabot
Copy link

jsf-clabot commented Mar 24, 2019

CLA assistant check
All committers have signed the CLA.

@ulivz ulivz changed the title fix: fix: check existence of res.getHeader fix: check existence of res.getHeader Mar 24, 2019
@codecov
Copy link

codecov bot commented Mar 24, 2019

Codecov Report

Merging #385 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #385   +/-   ##
=======================================
  Coverage   96.96%   96.96%           
=======================================
  Files           7        7           
  Lines         264      264           
=======================================
  Hits          256      256           
  Misses          8        8
Impacted Files Coverage Δ
lib/middleware.js 94.54% <100%> (ø) ⬆️

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 dba5e02...2337b4b. Read the comment docs.

@codecov
Copy link

codecov bot commented Mar 24, 2019

Codecov Report

Merging #385 into master will increase coverage by 0.08%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #385      +/-   ##
==========================================
+ Coverage   96.77%   96.86%   +0.08%     
==========================================
  Files          12       13       +1     
  Lines         279      287       +8     
  Branches       81       83       +2     
==========================================
+ Hits          270      278       +8     
  Misses          9        9
Impacted Files Coverage Δ
test/mock-express/index.js 100% <100%> (ø)
lib/middleware.js 94.64% <100%> (ø) ⬆️

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 eb2e32b...dca42ae. Read the comment docs.

@ulivz ulivz changed the title fix: check existence of res.getHeader fix: check existence of res.getHeader and set the correct Content-Type Mar 24, 2019
hiroppy
hiroppy previously approved these changes Mar 24, 2019
Copy link
Member

@hiroppy hiroppy left a comment

Choose a reason for hiding this comment

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

In any case, if we don't have res.getHeader will be an error here so I think this change is no problem.

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 don't support webpack-serve, it is deprecated and officially doesn't supporting, and we need tests

@alexander-akait
Copy link
Member

I strongly recommend migrate from webpack-serve to avoid this problem in future, also it is doesn't works with webpack@5, so you still need migrate on other solution than webpack-serve

@ulivz
Copy link
Contributor Author

ulivz commented Mar 25, 2019

@evilebottnawi But this issue is truly introduced by this package.

Why not responsible for your upstream if you regard your package as the cornerstone?

@alexander-akait
Copy link
Member

alexander-akait commented Mar 25, 2019

@ulivz upstream? As i said above webpack-serve is deprecated, but we can accept PR, need tests for this to avoid regression in future

@ulivz
Copy link
Contributor Author

ulivz commented Mar 26, 2019

Did you mean that I should write a test for KOA usage as https://github.com/webpack/webpack-dev-middleware/blob/master/test/tests/server.js

@alexander-akait
Copy link
Member

@ulivz no, just defined (mock) getHeader method as undefined and add test to ensure all works fine

@ulivz
Copy link
Contributor Author

ulivz commented Mar 27, 2019

@evilebottnawi Got it!

@ulivz
Copy link
Contributor Author

ulivz commented Mar 27, 2019

I tried to add test under test/tests/server.js, but unfortunately I found that I cannot cover the res.getHeader method under express since express depends on it under the hood.

ref: https://github.com/expressjs/express/blob/master/lib/response.js#L784

res.getHeader comes from http.ServerResponse.prototype since res in express inherits from it but KOA didn't do it.

So shouldn't I write a test for KOA usage?

Here is my test case:

  describe.only('custom Content-Type when res.setHeader is undefined', () => {
    before((done) => {
      app = express();
      app.use((req, res, next) => {
        // Cover getHeader at the prototype.
        res.getHeader = undefined;
        res.set('Content-Type', 'application/octet-stream');
        next();
      });

      const compiler = webpack(webpackConfig);
      instance = middleware(compiler, {
        stats: 'errors-only',
        logLevel
      });
      app.use((req, res, next) => {
        // Recover getHeader;
        delete res.getHeader;
        next();
      });
      listen = listenShorthand(done);
    });
    after(close);

    it('Do not guess mime type if Content-Type header is found', (done) => {
      request(app).get('/bundle.js')
        .expect('Content-Type', 'application/octet-stream')
        .expect(200, done);
    });
  });

@alexander-akait
Copy link
Member

Just mock value, no need import

@ulivz
Copy link
Contributor Author

ulivz commented Mar 27, 2019

Writing a new test or still in test/tests/server.js?

@alexander-akait
Copy link
Member

@ulivz server.js

@ulivz
Copy link
Contributor Author

ulivz commented Mar 27, 2019

Sorry for my poor intimate knowledge of sinon,I just read the docs of sinon, it told me:

Mocks (and mock expectations) are fake methods (like spies) with pre-programmed behavior (like stubs) as well as pre-programmed expectations.

But for now we need to mock a undefined, so how should I mock the getHeader and ensure the test work?

Or, do you mean that I should mock the express?

@alexander-akait
Copy link
Member

Yes, just mock express where getHeader is undefined

@ulivz
Copy link
Contributor Author

ulivz commented Mar 30, 2019

@evilebottnawi Tests updated and passed, could you help re-review this MR? Thanks.

This out of PR is very important to us. Thanks!

@ulivz
Copy link
Contributor Author

ulivz commented Apr 2, 2019

Any progress here?

@alexander-akait
Copy link
Member

@ulivz i was on vacation

@alexander-akait alexander-akait merged commit 56dc705 into webpack:master Apr 3, 2019
@ulivz
Copy link
Contributor Author

ulivz commented Apr 3, 2019

Thanks~

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