Question/Feature-request: Is there an easy way to trigger a route manually
- [x] Used appropriate template for the issue type
- [x] Searched both open and closed issues for duplicates of this issue
- [x] Title adequately and concisely reflects the feature or the bug
Feature Request
Use Case
I want to be able to trigger a server route manually.
I'm not sure if this is already possible but scanning the docs and old issues I could not find anything that sounded similar.
Example API
This could look something like this const response = await server.inject({ method: 'GET', url: '/' }) (fastify-like).
Are you willing and able to implement this?
If someone would point me in the right direction I could try doing a PR ... or ask my company to pay a small amount for someone else to do it. Let me know ...
I have a similar need — I want to be able to write a route handler that calls other routes, specifying the method, body, headers, params, etc. but in all other respects delegating to the original request.
I have this so far:
const intReq = new http.IncomingMessage(req.socket);
intReq.method = 'GET';
intReq.url = '/an-internal-route';
intReq.headers = req.headers;
const intRes = new http.ServerResponse(intReq);
server._onRequest(intReq, intRes);
Where server is a restify server instance, req is an incoming restify request, and http is the node http package.
It doesn't obviously fail, but it also does not obviously succeed. The primary difficulty is in constructing the new request and response class instances — I have little confidence I'm even close to doing something good and reasonable in this spike.
Further investigation reveals that the fastify light-my-request library seems very nicely suited for this purpose, but the wrinkle there is that the synthetic request that it creates does not have all of the methods that the restify request monkey patches into the http.IncomingMessage class. I'm inclined to patch those in in my own dispatch function, but restify does not export its patch functions in any way that I can see.
There might be a way to do it by manually messing with the instance prototypes, but maybe someone has a better idea.
Happy to report I have a working solution:
This needs to be run once, in order to add restify's monkey patched methods to the light-my-request Request:
const { inject } = require('light-my-request');
const { Request } = require('light-my-request/lib/request');
const patchRequest = require('restify/lib/request');
patchRequest(Request);
And then something along these lines:
const dispatch = server._onRequest.bind(server);
// accept-encoding of null disables gzip compression
const ireq = { method: 'get', url: '/your/internal-route', headers: { ...req.headers, 'accept-encoding': null } };
const res = await inject(dispatch, ireq)
Two things strike me as problematic about this — requiring sub-packages of restify and light-my-request, which may be outside of what they consider to be their public api, and similarly, using the restify _onRequest method. Otherwise, this seems eminently reasonable.
For those landing on this it looks like patching light-my-request's Request object is also no longer feasible
TypeError: Cannot set property closed of [object Object] which has only a getter
6 | // eslint-disable-next-line @typescript-eslint/no-var-requires
7 | const patchRequest = require('restify/lib/request');
> 8 | patchRequest(Request);