Comments (8)
Encapsulating state for middleware can be useful, but also a foot gun IMHO.
This can easily be achievable in user space or as a plugin. and there's nothing prohibiting you from extending Koa and overloading use for this effect. I have actually done this myself in a few production apps.
Sometimes I would just compose an object with Koa and a Router effectively overloading use
(through composition and delegation rather than inheritance though), but sometimes if I remember correctly I would just extend koa.Application#use
and check for objects.
I am not involved in Koa anymore so whatever I say is my own opinion but following the general design of Koa I would consider this to be bloat and better fitted as a plugin, much like routers are.
from koa.
Why no just passing the desired method from a class?
from koa.
This feature request is for increasing ergonomics/ DX. Especially when dealing with routes there's a fair amount of repetition.
Of course helper functions are possible or as you say just work around this, but I asked because it will result in more elegant code.
from koa.
Can you provide a reference for this pattern you suggest? My understanding is semantically it makes no difference: there is a method which koa would call. But instead of providing that method directly you suggest we give an object and koa will look for that special method by itself. Now I can't see how this would make the code nicer or more developer friendly.
from koa.
A specific example is that I want users to be able to build controllers as such:
class MyController extends ResourceController {
get(ctx: Context) {
/* ... */
}
}
And I would like users to be able to add this controller using this form:
app.use(new MyController())
My feature request would allow me to define the ResourceController
baseclass in a way that Koa can pick this up. Not having this feature requires me to either ask users to call something like:
app.use((new MyController())->mw())
Or add a helper function
app.use(mw(MyController))
Because this has to be done for each route/controller, this is kind of an annoying overhead. I went the helper function route for this, below is the full reference of my ResourceController
. But having built-in support for this would be nicer.
import { METHODS } from 'node:http';
import { Context, Middleware } from 'koa';
import { MethodNotAllowed, NotImplemented } from '@curveball/http-errors';
/**
* Takes a ResourceController subclass, instantiates it and returns
* a koa-compatible middleware.
*/
export function mw(cl: typeof ResourceController): Middleware {
const controller = new cl();
return controller.dispatch.bind(controller);
}
/**
* The ResourceController is a base class for controllers that
* maps HTTP methods like GET, PUT to class methods like 'get', 'put'.
*/
export class ResourceController {
constructor() {
// HEAD fallback. It could be desirable to reimplement HEAD faster, but this is an OK default and just as slow as GET but with fewer bytes sent.
if ('get' in this && !('head' in this)) {
(this as any).head = this.get;
}
}
options(ctx: Context) {
ctx.body = '';
ctx.set(
'Allow',
METHODS.filter(method => method.toLowerCase() in this).join(',')
);
}
dispatch(ctx: Context): void|Promise<void> {
if (!METHODS.includes(ctx.method)) {
throw new NotImplemented(`HTTP method not implmented ${ctx.method}`);
}
const classMethod = ctx.method.toLowerCase();
if (typeof (this as any)[classMethod] === 'function') {
return (this as any)[classMethod](ctx);
} else {
throw new MethodNotAllowed(`The ${ctx.method} method is not supported at this endpoint`);
}
}
}
from koa.
Well I would have done it like this:
A global middleware factory:
function ControllerObj(c, ...params) {
const controllerInstance = new c(...params)
return function mw(ctx, next) {
const method = ctx.method.toLowerCase()
if(typeof controllerInstance[method] !== 'function') {
ctx.throw(405)
}
controllerInstance[method](ctx, next)
}
}
A controller class:
class ControllerX {
constructor(aKnob) {
this.aKnob = aKnob // Some tweaks for this route
}
async get(ctx, next) {
ctx.status = 200
ctx.body = this.aKnob
await next()
}
// more methods here...
}
And finally:
app
.use(ControllerObj(ControllerX, 'desiredResponse'))
My belief is that this is not such a general pattern to be implemented in Koa. A plugin maybe...
from koa.
Sure, let's see what the maintainers say. Your approach doesn't really make a difference in terms of cognitive overhead.
from koa.
Completed?
from koa.
Related Issues (20)
- [fix] Some things cannot be found in the database where condition search, unless the where condition search ID HOT 3
- koa 2.14.7 No generics,I want to be able to add generics HOT 1
- [feat] when will koa 3.0 be released? HOT 3
- Koa main website example code snippets disappear HOT 4
- [feat] Support Web (WHATWG) stream, Blob and Response HOT 6
- Consider alternatives to http-assert (including none at all) HOT 4
- [fix] Send response as buffer HOT 4
- async issue on app.listen(...) HOT 4
- [fix] I can not get query parameters about Korean HOT 3
- [feat] Spanish translation for docs HOT 1
- Routing sucks, moving back to express. HOT 1
- [fix] ctx value persists to next request after mutating ctx object HOT 3
- if "\@" in url ,the redirect result doesn't match the host of the new URL() HOT 2
- [feat] Replace npm dependency "only" HOT 2
- [fix] Version 2.x introduced the URL object, which is not compatible with Node versions below 10.
- Client disconnect HOT 1
- [bug] TCP memory leak caused by aborted client connections when streaming data with node-fetch HOT 4
- Koa(2.15.3) Router Resolve the problem HOT 3
- Koa v3 Tracker HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from koa.