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

Curried Default Error Handler Failing #3657

Closed
JesterXL opened this issue May 16, 2018 · 6 comments
Closed

Curried Default Error Handler Failing #3657

JesterXL opened this issue May 16, 2018 · 6 comments

Comments

@JesterXL
Copy link

It appears that Express checks the function's arity to identify if it's an error-handler route. It works with a function, and works with an arrow function, but does not work with a Lodash curried function. I believe this is possibly because theFunction.length will print out 0 for curried functions, whereas function and ()=> will print out a true arity. However, I can't seem to find where in the code y'all are checking for this. I've tried to manually setting the theFunction.length to 3 or 4 to hack it, but no dice. Any pointers?

Works when you hit localhost:3000/error:

const express = require('express')
const curry = require('lodash/fp/curry')
const app = express()

app.get('/', (req, res) => res.send('Hello World!'))
app.get('/error', (req, res, next) => {
    next(new Error('boom'))
})

function genericErrorHandler(err, req, res, next) {
    console.log("err message:", err.message)
    res.status(500).send('Something broke!');
}
app.use(genericErrorHandler)

app.listen(3000, () => console.log('Example app listening on port 3000!'))

Doesn't work:

const express = require('express')
const curry = require('lodash/fp/curry')
const app = express()

app.get('/', (req, res) => res.send('Hello World!'))
app.get('/error', (req, res, next) => {
    next(new Error('boom'))
})

const genericErrorHandler = curry((prefix, err, req, res, next) => {
    console.log(`${prefix} err message:`, err.message)
    res.status(500).send('Something broke!');
})
const curried = genericErrorHandler('🐮')
curried.length = 4 // I tried, heh
app.use(curried);

app.listen(3000, () => console.log('Example app listening on port 3000!'))
@dougwilson
Copy link
Contributor

You're correct, this is the documented way we determine what is a middleware and what is an error middleware. I don't think you can set the length of a function in javascript after the fact; it has to have the arguments at the time of declaration.

@dougwilson
Copy link
Contributor

dougwilson commented May 16, 2018

For example:

const genericErrorHandler = (prefix) => (err, req, res, next) => {
    console.log(`${prefix} err message:`, err.message)
    res.status(500).send('Something broke!');
}

@wesleytodd
Copy link
Member

I have this open, and plan on switching it to the implementation at the bottom soon. Would love input.

pillarjs/router#59

@JesterXL
Copy link
Author

Got it, thanks. I'll just create a wrapper function with that value fixed.

@JesterXL
Copy link
Author

BTW, those stumbling here, I found way to make this work while still allowing a longer arity for easier unit testing & acting like a curried function using default parameters.

Take the curried function:

const genericErrorHandler = curry((prefix, err, req, res, next) => {
    console.log(`${prefix} err message:`, err.message)
    res.status(500).send('Something broke!');
})

And just build a wrapper (or ditch the curried one), and move the default curried left parameters to the end with defaults:

const genericErrorHandler = (err, req, res, next, prefix='some value') => {
    console.log(`${prefix} err message:`, err.message)
    res.status(500).send('Something broke!');
})

In my case, my prefix was a function; both work, the arity is always 4:

const specialLog = ()=> {...}
const genericErrorHandler = (err, req, res, next, specialLogFunction=specialLog) => {
   ... 
   specialLogFunction(err)
   ...
})

@wesleytodd
Copy link
Member

wesleytodd commented May 18, 2018

Also, if anyone is interested, you can do this with a simple middleware factory function:

const genericErrorHandler = (prefix) => {
  return (err, req, res, next) => {
    console.log(`${prefix} err message:`, err.message)
    res.status(500).send('Something broke!')
  }
}
app.use(genericErrorHandler('foo'))

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

No branches or pull requests

3 participants