-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Expose a way to inject middleware in the server pipeline for adapt-node #334
Comments
I feel like we need to be specific about the use cases here. The downside of a catch-all escape hatch is that it means that the answer to various problems becomes 'use |
People are going to have use cases we haven't imagined. I'm not sure we should block them from being able to use SvelteKit. I really think this is something that's going to be needed Just a few minutes ago someone was complaining on Discord that they can't use passport. I've already been frustrated by not being able to use Multer or Formidable (#70 (comment)). There may be solutions to these that we can build that would be better, but there's a whole ecosystem of solutions out there that we're stopping people from using and it seems impossible that we'd reimplement all of them |
File uploads should be handled out of the box, and serverless apps need auth too. I really don't think multer, formidable and passport are the right answers in 2021 |
I think those were just some specific examples, showing that in general it's not really predictable what the whole JS ecosystem does, and that it may need support for middleware from SvelteKit. Also I don't think we should prevent people from using libraries which are battle-tested and which they want to use. If this was supported and people would reach more for |
I'm crazy, so the way I've been doing this for a production app is:
In lieu of an actual way to do "serverfull" projects, this kind of hacky thing will sprout up. |
And that's fine — that's the system working. Having a little bit of friction gives you a much clearer picture of which use cases warrant first-class support. If the frictionless escape hatch is so big that everything just gets dumped in there, it means the framework isn't providing sufficient value, especially if it steers people away from serverless platforms. (Short of @GrygrFlzr's solution, adding arbitrary middleware to If the question is 'what do you need to do?' the answer is never 'I need to use Multer' or 'I need to use Formidable' or 'I need to use Passport'; it's 'I need to handle file uploads' or 'I need to use OAuth providers for authentication'. These are solvable problems, and I would go so far as to argue that those two problems fall into SvelteKit's domain. The future-proof thing to do isn't to throw our hands up and say 'we can't possibly anticipate everything people will need to do, therefore we should abdicate the responsibility to the ecosystem of Express middleware', it's to understand (from specific examples) how to make it possible for people to solve arbitrary problems in an environment-agnostic way (i.e. doesn't rely on To be clear, I'm not suggesting that SvelteKit should include equivalents for every Express or Fastify middleware out there, just that we should provide the necessary hooks for an ecosystem of such things to exist. |
I think the goal of adapters should be to be quite flexible. If people want to user serverless that's great and if they don't that's also great. Serverless may not be the best for every use case and we shouldn't force it on people. I agree we should support all these use cases in serverless environments. Passport offers authentication with over 500 different methods (oauth 1, oauth 2, bearer tokens, OpenId, freeagent, TOTP, active directory, etc., etc.). It seems like a terrible burden to place on the community that they should have to reimplement passport and all its plugins in a SvelteKit-compatible way using our unique APIs if you're a user for whom |
I was recently in the position of wanting a Sapper app with a really quick and dirty basic auth thing in front of it. (It wasn't anything highly sensitive, I was just trying to prevent randos from using up the API call allotment for an underlying service.) I didn't want a fully fledged proper authentication system, I just wanted to be able to insert some code that checked for a specific HTTP header and either let the request proceed or intervene and return a 401. This was trivial to do when I was able to write Express middleware. It's not a perfect API, but the Express middleware contract is both well known and lets people do just about whatever weird shit they'd like. There are going to be tons of problems that are way too niche to have an official tailored solution for. (And I wouldn't say that just because people are having trouble listing them doesn't mean that they don't exist.) Coming up with another API that was as flexible sounds like a hassle for us because we'd need to outsmart this very battle-tested API, and also sounds like a hassle for users, because it's something new they need to learn. |
I'll be (perhaps too) honest: Every time I use Passport I weep. I'm always copying and pasting a bunch of code that I don't really understand, and I have absolutely no idea what it's doing under the hood. I daresay that '500 different methods' overestimates the scale of the problem; there's a very long tail. I get that there's a rich ecosystem of Express middleware. There's also a rich ecosystem of React components! You can use those React components in your SvelteKit app if you really want to, but there's going to be friction, because we don't believe that that's the best way to build apps. So I think we need to look at this the same way: it should probably be possible to use Passport and other middleware, but I don't think we should encourage it by making it idiomatic. Making everything except |
What would you consider a non-idiomatic way of using other middleware? Using a forked version of adapter-node that supports that? |
If adapters had some way to intervene in |
To recap conversation here and on Discord:
I propose that we add a export function handler(request, render) {
if (!request.headers['x-the-header-conduitry-was-using']) {
return { status: 401 };
}
// otherwise fall through to default handler
return render(request);
} ...but also to support existing middlewares in an environment-agnostic way, albeit in a way that makes people feel just nauseous enough to consider a more idiomatic solution: import { applyMiddleware } from 'some-third-party-library';
const middleware = get_auth_middleware_somehow({...});
export function handler(request, render) {
return applyMiddleware(request, render, middleware);
} In this example, // this is incorrect and incomplete, purely for illustration
function applyMiddleware(request, render, middleware) {
return new Promise((fulfil, reject) => {
const req = {
url: request.path,
method: request.method,
headers: request.headers,
// ...
};
const res = {
status: null,
headers: {},
body: '',
writeHead(status, headers) {
res.status = status;
Object.assign(res.headers, headers);
},
write(data) {
res.body += data;
},
end() {
fulfil({
status: res.status,
headers: res.headers,
body: res.body
});
}
};
});
middleware(req, res, err => {
if (err) {
reject(err);
} else {
fulfil(render(request));
}
});
} There isn't a great place to put this — // src/hooks.js
export function prepare({ headers }) {
return {
context: {...},
headers: {...}
};
}
export function getSession({ context }) {
return {...};
}
export function handle(request, render) {
return render(request);
} Arguably, returning // src/hooks.js
export function getContext({ headers }) {
const context = {...};
return context;
}
export function getSession({ context }) {
return {...};
}
export function handle(request, render) {
const rendered = render(request);
return {
...rendered,
headers: {
...rendered.headers,
'x-custom-header': 'blah'
}
};
} (I also think that maybe Thoughts? |
I started working on this, primarily to learn the Kit Codebase better. Don't know if its the right approach but it works in the sandbox. You can take a look here, i probably won't open a pr because i don't have enough time to continue: https://github.com/pixelmund/kit/tree/add-handle-and-hooks |
* replace setup with hooks (#334) * changeset * lint * docs and types * rename empty setup module * tweak wording * fix realworld example * lets just make it async * explain resolve_entry * reduce indentation
Closing this now that we have hooks: https://kit.svelte.dev/docs#hooks |
Server-sent events may be such a use case. It doesn't seem possible with hooks. |
@GrygrFlzr I came up with something exactly like what you mentioned here. |
How about making it easier to combine SvelteKit adapter-node generated code with other connect/express like middleware by not exporting a full featured polka server instance, but a requestHandler instead? |
Similar to #333
It would be valuable to be able to insert additional handlers in the adapt-node server pipeline to customize the serving behavior based on deployment env.
https://github.com/sveltejs/kit/blob/master/packages/adapter-node/src/server.js#L30
In sapper we directly exposed the server making this possible but now in sveltejs + adapt-node we do not expose this dial. It would be nice to have an escape hatch
The text was updated successfully, but these errors were encountered: