-
-
Notifications
You must be signed in to change notification settings - Fork 174
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
Why no throwing from middleware? #12
Comments
|
Yeah, I'm talking about the ability to throw from middleware. On one hand, I could believe that not having it would entail a measurable performance improvement; on the other hand, not having it means that your server can potentially come down over anything. Now that I think about it, I guess, if a polka app is itself callable as middleware (as is the case with Express, and I'm pretty sure Connect before it), you could probably introduce all this by having a layer around your app that hands off the request within a try/catch (or, in the case of Promise rejections, wrapping it in a Promise that resolves at the end of the middleware - which would also catch synchronous throws). |
Yeah, definitely. There's an HTTPS example I added that shows how a Polka app can be embedded. With the most recent Loop changes, I haven't measured the performance impact, so I could try now. But before, it was pretty bad! |
I'm thinking what would make sense for implementing catching, if it really is that much of a burden in production (and I know it certainly can be, due to all the stack-trace baggage the system otherwise doesn't have to maintain), would be to add a method to Polka that looks something like this (without looking at the implementation - the internals would probably allow for something lighter weight than instantiating a new instance just to use itself as middleware):
This would mean that an app could add a call like It would also let the app have a more granular instrumentation policy, applying |
Actually, I just looked, and Polka neither exposes itself as a function (which is what I meant by "allows itself to be used as middleware") nor exposes a Here's a maybe clearer way to express it, if Polka.prototype.protected = function protected(active) {
if (active)
return polka().use((req, res, next) => {
new Promise((resolve, reject) =>
this.handle(req, res, err => err ? reject(err) : resolve())
).then(next, next);
});
else return this;
} |
If I were to go a route other than function onError(req, res, next, err) {
req.pathname.includes('foo') && next(); // ignore
console.log(`> ERROR: ${req.method}(${req.url}) ~>`, err);
res.statusCode = err.code || 500;
res.end(err.toString() || 'Oops!');
}
polka({ onError }).use(...);
//=> internally
let next = err ? this.onError(req, res, next, err) : loop(); |
I might even go that route anyway & just call the I'll have time this weekend to flush out more of this refactor, and I'll be considering this. 👍 |
Okay, but:
Also, do forgive my impertinence, but are you not aware that quaternary error-handling middleware functions are the established format for handling errors in the Express ecosystem? |
It's not Polka's job to clean up everyone's mess. You have to catch your own crap, as dirty as it may be. If you're not catching your own Promise rejections, you're either writing the middleware incorrectly or just setting yourself up for failure, regardless of the server framework used. That link gives the same advisory note that I do; but their is less noticeable:
Nothing on that front changes when using sync or asynchronous functions. At this point, I really don't care about The primary goal of Polka is to be a familiar API, not exact, and perform as close to native If |
For example, this is wrong regardless of server choice: const sleep = ms => new Promise(r => setTimeout(r, ms));
app.use((req, res, next) => {
sleep(5e3).then(_ => {
console.log('> ok, NOW, im done');
next();
});
next();
}) |
@stuartpb each middleware should handle its own errors but if you are that crazy for throwing you can implement something like this const http = require('http');
const polka = require('polka');
const app = polka({ createServer: false });
const server = http.createServer((req, res) => {
try {
app.handler(req, res);
} catch (err) {
console.error(err);
app.send(res, 500, err.message);
}
});
server.listen(8080); createServer option will work after #13 gets merged @stuartpb if you want it so bad to be internal you could start new issue on having similar wrapper like shown above in npm module |
hey @lukeed I'm koa user and I am doing a lab with polka... One thing that I fell missing: Put middleware in specific route polka()
.get('/', home)
.use(bodyparser)
.post('/data-json', dataJson)
.use(auth, bodyform)
.post('/data-form', dataForm)
.listen(3000).then(_ => {
console.log(`>>> Running on 3000`)
}) This way, all routes will pass through the Could be: polka()
.get('/', home)
.post('/data-json', bodyparser, dataJson)
.post('/data-form', auth, bodyform, dataForm)
.get('/another', another)
.listen(3000).then(_ => {
console.log(`>>> Running on 3000`)
}) Regards!! |
@lukeed never mind... 👆 |
Hey, welcome! Ya theres that, but also this issue #18 I am leaning towards having this in |
Closing this as it's an older discussion & still stands by my reasons for excluding it. Thank you though! 🙏 |
Will be included in the 1.0 push for Express compatibility – and especially because the |
Great work on this lib, thanks! |
Today, what's the correct way to avoid the app crash if some error do not get catch? |
@neves At this point I'd use const polka = require('polka');
const app = polka().get('/', (req, res) => {
throw new Error('Hello');
});
// Redefine `app.handler` w/ try-catch
// You only have to do this on the MAIN/TOP application!
const old = app.handler;
app.handler = function (req, res, info) {
try {
old.apply(app, arguments);
} catch (err) {
console.log('> I caught error:', err);
res.end('Oops~');
}
}
app.listen(3000); |
polka@next works like a charm, with one little problem. If I instantiate a new polka inside a middleware (sup-apps) I need to define onError again, but the expected behaviour was to bubble the exception to the main/top application. Can you confirm that? |
No, every Polka instance has a default onError handler. If you want to customize it, it has to be defined. It's best to define your own router file/package and then import that where needed. I do this in all larger applications. // router.js
import polka from 'polka';
function onError(err, req, res, next) {
// Custom...
}
export default function () {
return polka({ onError });
}
// users.js
import router from './router';
router()
.use(...)
// Etc |
Great. That should work. |
Eventually I'll have a full Polka starter kit, but I'm just using Rollup to build. You can also just do everything above using |
I have four questions:
The text was updated successfully, but these errors were encountered: