Intercepting requests

Learn how to intercept outgoing requests.

In order to send a mocked response for a request, we have to intercept that request first. In Mock Service Worker, request interception is performed by functions called request handlers.

A request handler function looks like this:

// Intercept an HTTP GET request which path
// matches the "predicate", and resolve it
// using the given "resolver" function.
http.get(predicate, resolver)
 
// A similar request handler for a GraphQL mutation.
graphql.mutation(predicate, resolver)

Learn more about Request handlers.

In the context of this page, we will focus on how request handlers enable us to intercept request, omitting the resolver part for now. The way the request interception is done will differ based on the API type we are mocking, reflecting the domain language of that API.

HTTP requests

HTTP requests can be intercepted using the http request namespace. Methods in that namespace represent HTTP methods (http.get(), http.post(), etc.) and have the same function call signature expecting two arguments:

  • predicate (string | RegExp), a request path predicate;
  • resolver, (Response resolver), a function that decides how to handle an intercepted request.

For example, here’s a request handler for a GET /pets request that returns a list of pets:

import { http, HttpResponse } from 'msw'
 
http.get(
  // The "/pets" string is a path predicate.
  // Only the GET requests whose path matches
  // the "/pets" string will be intercepted.
  '/pets',
  // The function below is a "resolver" function.
  // It accepts a bunch of information about the
  // intercepted request, and decides how to handle it.
  ({ request, params, cookies }) => {
    return HttpResponse.json(['Tom', 'Jerry', 'Spike'])
  },
)

Learn more about the http request namespace.

HTTP request matching

The nature of the predicate argument allows you to intercept HTTP requests by multiple criteria. Let’s take a closer look at all possible ways to write a request predicate.

Request pathname

When the predicate argument is a string, only the requests whose pathname matches that string will be intercepted. This works the same for both relative and absolute URLs!

export const handlers = [
  http.get('/pets', petsResolver),
  http.post('https://api.github.com/repo', repoResolver),
]

You can include special tokens in the request predicate string to intercept multiple requests at the same time. One of the most common tokens is a wildcard (*), which matches any string in its place:

// Intercept all GET requests to "/user":
// - GET /user
// - GET /user/abc-123
// - GET /user/abc-123/settings
http.get('/user/*', userResolver)

Request pathname matching in MSW is using path-to-regexp library. Learn more about all the supported path tokens in its documentation.

When providing request pathnames, make sure to exclude any query parameters. Query parameters have no effect on resource identification and instead serve as the means to send additional information to the server. If MSW encounters a query parameter, it removes it and prints a warning that you should remove it too. The values of the query parameters is still available to you in the request.url property in the response resolver.

Regular expression

You can use Regular expressions as the request path predicate. Only the request whose URL matches the provided expression will be intercepted. Utilize the dynamic nature of regular expressions to handle more advanced request matching scenarios.

// Intercept DELETE requests matching the regular expression.
// - DELETE /settings/sessions
// - DELETE /settings/messages
http.delete(/\/settings\/(sessions|messages)/, resolver)

GraphQL API requests

GraphQL servers are often implemented via HTTP so you can use the same http request namespace to intercept and resolve them. However, MSW provides a first-class support for intercepting GraphQL APIs using a designated graphql request namespace. Methods of that namespace represents GraphQL operation types (graphql.query(), graphql.mutation()) and have the same function call signature expecting the following arguments:

For example, here’s a request handler for a ListPets query that returns a list of pets:

import { graphql, HttpResponse } from 'msw'
 
export const handlers = [
  graphql.query('ListPets', () => {
    return HttpResponse.json({
      data: {
        pets: [
          { id: 1, name: 'Tom' },
          { id: 2, name: 'Jerry' },
          { id: 3, name: 'Spike' },
        ],
      },
    })
  }),
]

GraphQL request matching

By default, MSW matches all GraphQL requests, regardless of their endpoint, by their operation type and operation name. The easiest way to visualize it is to imagine an actual GraphQL query your application makes:

query ListPets {
  pets {
    id
    name
  }
}

In the query above, query is the operation type while ListPets is the operation name.

Let’s take a look at all possible ways to define a GraphQL request predicate.

GraphQL operation name

When the GraphQL request predicate is a string, only the operations whose name matches that string will be intercepted.

// Intercept GraphQL queries that match the provided name.
// - "query GetUser { ... }"
graphql.query('GetUser', userResolver)

Regular expression

Similar to the HTTP request matching, you can use Regular expressions to gain more control over what GraphQL operation names should be intercepted.

// Intercept GraphQL mutations that match the regular expression.
// - "mutation CreateUser { ... }"
// - "mutation CreateAuthor { ... }"
graphql.mutation(/(CreateUser|CreateAuthor)/, resolver)

Endpoint URL

In more advanced scenarios, you can narrow down the GraphQL request interception by binding it to a specific HTTP endpoint. This is particularly useful when you need to distinguish between same operation types/names that are performed against different GraphQL APIs in your application.

import { graphql } from 'msw'
 
const github = graphql.link('https://api.github.com/graphql')
const stripe = graphql.link('https://api.stripe.com')
 
export const handlers = [
  github.query('GetUser', githubUserResolver),
  stripe.query('GetUser', stripeUserResolver),
]

Learn more about the graphql.link() API.

Common questions

How do I use relative URLs in Node.js?

You don’t. In Node.js, there is nothing to be relative to. If you are describing a network behavior for a Node.js application, use the absolute URLs you are requesting. If you are using MSW with a Node.js-based test runner, like Jest or Vitest, configure those runners accordingly to support relative URLs (i.e. polyfill the window.location object).