koajs / discussions

KoaJS Discussions
2 stars 2 forks source link

Internal sub-request #23

Open evert opened 6 years ago

evert commented 6 years ago

Dear Koa devs,

Super happy with Koa. We've been using it for over a year.

I'm facing an issue where I want to do an 'internal subrequest'. What this means is that a real HTTP request comes in, and I want to write a middleware that creates a brand new (fake) HTTP request and return the result.

This middleware will then take the result and do some post-processing before returning it.

Is there a standard way to solve this problem with Koa? I want to avoid doing a 'real' HTTP request on the local server, because it seems like a lot of overhead. I don't really want to invoke the TCP/HTTP stack, although my prototype does use that approach.

Any pointers here are welcome!

fl0w commented 6 years ago

I'm having issues relating question to a use case which in turn makes the question weird. What problem are you trying to solve?

In any case, either you just write a middleware which you use first (and thus last), or if you want to use native http server you could wrap app.middleware maybe?

evert commented 6 years ago

There's a few different use-cases possible, but the one I'm solving right now is that I'm working on an API that uses HAL. HAL has a feature to allow embedding of other resources.

What I want to do is intercept a request and automatically do this. Basically I want to make a 'fake' GET request that goes through the entire stack, take the response and embed the result in the true parent-request.

I've ran into a few cases like this in the past. This was PHP, but it might give a bit more context. In the PHP case I implemented a CalDAV server. In some cases you'll want to for example get some information about a specific user (identified by uri). Users are also represented as HTTP resources, so to do this, it made the most sense to just fake a HTTP request and get the user information through a local GET request. That way I could keep the 'thing' that exposes user information completely separate from the middleware that needed it.

There's also cases where I might need to see what a HTTP request would yield if it were made. For instance, I have a need to do internal HEAD requests and see what Content-Types come, and which Allow headers.

After some research I guess what I think I need to do is construct a fake 'Koa Context', maybe using a package such as node-mocks-http, but I wanted to see if the Koa authors also consider this the sanest way to do this.

Thanks for looking into this!

jmealo commented 6 years ago

NGINX supports this if you don't mind pushing it up the stack. (see: openresty and ledge)

evert commented 6 years ago

Interesting, but yea I really don't want to have to do that =)

I think the node-mocks-http package will get me there though. I haven't had a chance to test this, but I'd also imagine that I'd need something similar for HTTP2 Push anyway.

likegun commented 6 years ago

@evert Something like this?

    var Koa = require('koa');
    var Router = require('koa-router');

    var app = new Koa();
    var router = new Router();

    async function getUser(ctx, next) {...}
    router.get('/user/:id', getUser);

    router.get('/user/:id/someinformation', async () => {
        const fakeContext = //get fake context somehow
        await getUser(fakeContext);
        const user = fakeContext.body;
        //...rest code
    })

    app
    .use(router.routes())
    .use(router.allowedMethods());
RWOverdijk commented 5 years ago

Has anyone solved this? I want to translate websocket events to requests so I can reuse the same code for both websockets and API calls, but I haven;t been able to figure out how to do this besides actually calling localhost with for example fetch.

evert commented 5 years ago

Node-mocks-http can do this. I ended up taking a more drastic approach and write my own koa-inspired framework fixing a few other things that were hard to do

RWOverdijk commented 5 years ago

@evert Thanks.

robertkraig commented 4 years ago

There are usecases, but in another framework, you might check https://stackoverflow.com/questions/16520691/consuming-my-own-laravel-api, where you may have a maintenance method which does some thing, or.. you may have a cli workflow which needs to automate the creation of a few things. Instead of having to write all that same logic somewhere else considering the interconnectedness of typical codebases, you can just instantiate a new request internally and it never has to hit the network, it simply calls within the runtime of the nodejs process. I think it's mostly useful for tooling & writing utilities which do things.

evert commented 4 years ago

My usecase was doing bulk requests and doing programmatic HTTP/2 push. This is what I came up with if anyone is interested:

https://github.com/curveball/core