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

[Fixes #163] Don't propose "default" format when provided with an Object as fmt #164

Closed
wants to merge 6 commits into from
Closed

[Fixes #163] Don't propose "default" format when provided with an Object as fmt #164

wants to merge 6 commits into from

Conversation

javierfernandes
Copy link

@javierfernandes javierfernandes commented May 6, 2018

Changing default usage of the "default" format, which is deprecated to suggest using the "combined" format.

This fixes this case morgan({})
It was proposing you to use morgan('default') which is deprecated. Now it says

morgan deprecated morgan(options): use morgan(format, options) instead

Testing

I've added a new kind of test (/test/deprecations.js) because /test/morgan.js was suppressing all deprecation message.
There was no other test trying to capture and assert deprecations.

Also, I believe that this new kind of test could help this other PR #153 that was criticized because it was not asserting about the deprecation message.

Note

Notice also that this doesn't actually handle the problem of trying to use morgan in a wrong way, using it directly as a middleware instead of calling it as a function to get the middleware.
That can be done (with one of this new kind of test :P) introducing a new check here

  if (format && typeof format === 'object') {
    opts = format
    fmt = opts.format || 'combined'

    // smart deprecation message
    if (format.baseUrl) {
       deprecate('morgan(options): instead of "app.use(morgan)", you must use morgan like this "app.use(morgan(\'combined\')"')
    } else {
      deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead')
  }

Note that format.baseUrl is basically just a way to try to recognize that the first arg is express "request" object, which means that you have used morgan fn directly as a middleware. Maybe there is a better way to check that :)

I'll leave that to you or another PR, since I'm not sure about the deprecation message.
And actually I'm not sure that case should be handle as a deprecation warning message. I think that in that case the whole thing should blow up with an exception, because it won't probably work at all. Right ??

Cheers !!

Changing default usage of the "default" format, which is deprecated to suggest using the "combined" format
@javierfernandes javierfernandes changed the title [Fixes #163] propose "combined" format instead of "default" when provided an Object arg as fmt (instead of string) [Fixes #163] propose "combined" format instead of "default" when provided an Objectas fmt (instead of string) May 6, 2018
index.js Outdated
@@ -446,7 +446,7 @@ function format (name, fmt) {

function getFormatFunction (name) {
// lookup format
var fmt = morgan[name] || name || morgan.default
var fmt = morgan[name] || name || morgan.combined
Copy link
Author

Choose a reason for hiding this comment

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

I changed this one also thinking that if "default" is considered as deprecated then it shouldn't be used as a default, right ?

But, although I could create a unitary test for this function along, it didn't make much sense. Then I was not able to create a particular test for this change. I just make sure all other tests kept running fine.

But it would be great to get a confirmation about this change.
Thanks !

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea, this change will break people, so you'll have to determine a different way to make the change. The formats are slightly different, which is why one is deprecated and didn't just change the default without a message if that makes sense.

index.js Outdated
@@ -62,7 +62,7 @@ function morgan (format, options) {

if (format && typeof format === 'object') {
opts = format
fmt = opts.format || 'default'
fmt = opts.format || 'combined'
Copy link
Contributor

Choose a reason for hiding this comment

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

So this will break existing logs due to the format change, right? The date formats are different between default and combined, so you can't just change the default value of format.

@dougwilson
Copy link
Contributor

And actually I'm not sure that case should be handle as a deprecation warning message. I think that in that case the whole thing should blow up with an exception, because it won't probably work at all. Right ??

Yes, though this is a fundamental issue you can do to any middleware module out there. Perhaps there is a change you can make to Express on this to catch the mistake instead of needing to change every single middleware that exists with whatever the check they should use is. That would be the biggest win for everyone 👍

… check for using deprecated node api has no sense :S
…the default format because it was going to break the format. Introduced a new test for deprecation when explicitely using the default format
@javierfernandes javierfernandes changed the title [Fixes #163] propose "combined" format instead of "default" when provided an Objectas fmt (instead of string) [Fixes #163] Don't propose "default" format when provided with an Object as fmt May 6, 2018
originalConsoleError = process.stderr.write

process.stderr.write = function write (chunk, encoding) {
/* eslint node/no-deprecated-api: 0 */ // this is actually trying to be compat with older node
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than disabling it, I would follow the suggestion of the linter and use safe-buffer instead.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I thought you wouldn't like to add a new package just for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's just a devDependency since this is a test.

return errors.map(function (e) { return removeANSI(e.toString('utf8')) })
}
before(function () {
originalConsoleError = process.stderr.write
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I don't bother writing tests for these deprecation messages at all, but if you feel so inclined, I would say please don't do it by replacing process.stderr.write -- mocha itself may try to write there. Instead capture the messages through a listener: https://www.npmjs.com/package/depd#processondeprecation-fn

Copy link
Author

@javierfernandes javierfernandes May 6, 2018

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

No, because that is the module itself, to validate its writing to stderr. Modules embedding depd should use the listener hook only (i.e. they should follow the README).

errors = []
})

it('should tell you to use morgan "combined" if format arg is an object', function () {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there is a typo somewhere as the description doesn't match the actual test. From looking at it, I think the description is what just needs the update 👍

fmt = opts.format || 'default'

// smart deprecation message
deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead')
deprecate('morgan(options): use morgan(' + (typeof opts.format === 'string' ? JSON.stringify(opts.format) : 'format') + ', options) instead')
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! This makes a lot of sense -- it's basically just telling you to use (format, options) instead of echoing a format you didn't provide. That makes a lot of sense.

@javierfernandes
Copy link
Author

(couldn't reply to the comment inlined)

Yes, though this is a fundamental issue you can do to any middleware module out there. Perhaps there is a change you can make to Express on this to catch the mistake instead of needing to change every single middleware that exists with whatever the check they should use is. That would be the biggest win for everyone

That is not possible unless you are in a typed language. Express app.use() expects a function, and morgan is a function as well as the return value from morgan().
There is no way express can check that. Not even checking cardinality because I that would restrict you from doing something like app.use( (...args) => )

@dougwilson
Copy link
Contributor

Then if it's not possible to fix, then I think it's best left to the README to show the proper usage. Like I said this issue can happen to any middleware, and if the solution is to go and pull request every single middleware out there, then I am a big 👎 on that and won't take a change in this module for that. If the solution is to used a typed langauge, then you can use typescript which would have caught this.

@expressjs expressjs locked as too heated and limited conversation to collaborators May 6, 2018
@expressjs expressjs deleted a comment from javierfernandes May 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants