Msw: Middleware for Requests

Created on 30 Nov 2020  路  5Comments  路  Source: mswjs/msw

Is your feature request related to a problem? Please describe.
Middlewares would help in building dev tools/extend MSW without having to fork the repo.

Let's say we want to "monitor" all the requests that are responded by the server. So that we can assert the requests made.
Middleware/emitting responded event would help in building that.

Describe the solution you'd like
Should be able to add "middleware" or event emitted.

server.middlewares(middleware)

Describe alternatives you've considered
Right now to achieve this, we can add some logic to catch request in each handler.

let loginRequests = [];

server.use(
    rest.post('/login', (req, res, ctx) => {
        loginRequests.push(req);
        return res(ctx.json({ data: 'data'}));
    }),
);

But this would have to duplicated and we can't reliably abstract this logic out.

feature discussion

Most helpful comment

We can establish an event-based API that could also support request start/finish notifications (#388) for users to execute their logic.

const worker = setupWorker(...)
worker.events.on('request-start', listener)
worker.events.on('request-end', listener)

You could then use this API in your tests to monitor all requests like so:

const loginRequests = []
const server = setupServer(...)

server.events.on('request-intercepted', (req) => {
  loginRequests.push(req)
})

Would this work for your use case?

All 5 comments

Hey, @balavishnuvj. Thanks for raising this.

I think this feature would be useful, yet let's try to come up with a few more usage examples for it? Once there are more use cases it can handle, we can have a better look at the end API.

We can establish an event-based API that could also support request start/finish notifications (#388) for users to execute their logic.

const worker = setupWorker(...)
worker.events.on('request-start', listener)
worker.events.on('request-end', listener)

You could then use this API in your tests to monitor all requests like so:

const loginRequests = []
const server = setupServer(...)

server.events.on('request-intercepted', (req) => {
  loginRequests.push(req)
})

Would this work for your use case?

yeah emitting event would work well for this use case.

Since our use case is just to assert and check for any misbehaving network parts, we set up a custom network recorder for one of our codebases, msw could possibly adopt a variant of this:

This was heavily inspired by the Network panel in Chrome devtools.

export type NetworkTransaction = {
  request: HttpRequest<any>;
  response: HttpResponse<any>;
}

export type NetworkRecording = {
  readonly transactions: ReadonlyArray<NetworkTransaction>;
  readonly lastRequest: NetworkTransaction['request'];
  stop(): void;
}

export type NetworkRecordingConfig = {
  /**
   * Sets the limit of the recorder at which `afterLimit` action will be taken
   *
   * @default 20
   */
  maxKeyframes?: number;

  /**
   * Action to take once max limit is reached.
   *
   * `'stop'` - stops the recorder
   *
   * `'fifo'` - first in, first out. shifts the frame stack by one to make space for a new frame
   *
   * @default 'stop'
   */
  afterLimit?: 'stop' | 'fifo';

  /**
   * Only record frames who's request URL match the given pattern
   *
   * By default will record all requests and responses until max limit is reached
   */
  filter?: RegExp;
}

const createServer = () => ({
    startNetworkRecording: (config: NetworkRecordingConfig) => { /* implement */ }
})

You can now use the Life-cycle events API.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kettanaito picture kettanaito  路  3Comments

mainfraame picture mainfraame  路  3Comments

dashed picture dashed  路  4Comments

dashed picture dashed  路  3Comments

danielstreit picture danielstreit  路  3Comments