响应解析器

响应解析器是一个控制如何处理(解析)被拦截请求的函数。

¥Response resolver is a function that controls how to handle (resolve) the intercepted request.

例如,你可以这样使用 200 OK Hello World! 响应响应 GET /greeting 请求:

¥For example, this is how you would respond with a 200 OK Hello World! response to a GET /greeting request:

import { http, HttpResponse } from 'msw'
 
export const handlers = [
  // Describe what request to intercept...
  http.get('/greeting', () => {
    // ...and how to respond to it.
    return new HttpResponse('Hello world!')
  }),
]

参数

¥Arguments

响应解析器为你提供一个参数,该参数是一个包含有关被拦截请求的大量信息的对象。

¥Response resolver provides you with a single argument, which is an object containing a bunch of information about the intercepted request.

http.post('/post/:postId', async ({ request, params, cookies }) => {
  const { postId } = params
  const requestBody = await request.json()
})

常见参数

¥Common arguments

以下数据可用于每个拦截的请求,无论它是 REST API 还是 GraphQL 请求。

¥The data below is available for every intercepted request, regardless if it’s a REST API or a GraphQL request.

名称类型描述
requestRequest拦截请求的获取 API 请求表示。
requestIdstring拦截请求的 UUID 字符串标识符。
cookiesRecord<string, string>请求 cookie。
paramsRecord<string, string[] | string>请求路径参数。

以下是如何在响应解析器中访问拦截的请求路径参数的示例:

¥Here’s an example of how to access the intercepted request path parameters in the response resolver:

http.get('/post/:postId', ({ params }) => {
  const { postId } = params
})

GraphQL 参数

¥GraphQL Arguments

以下数据仅适用于 GraphQL 请求。

¥The data below is only available for GraphQL requests.

名称类型描述
querystringGraphQL 查询字符串。
variablesRecord<string, unknown>拦截查询的变量。
operationNamestringGraphQL 操作名称(例如 GetUser)。

以下是如何在响应解析器中访问 GraphQL 变量的示例:

¥Here’s an example of how to access GraphQL variables in the response resolver:

import { graphql, HttpResponse } from 'msw'
 
export const handlers = [
  graphql.query('GetUser', ({ variables }) => {
    const { userId } = variables
 
    return HttpResponse.json({
      data: {
        user: {
          id: userId,
        },
      },
    })
  }),
]

解析器说明

¥Resolver instructions

响应解析器必须 always 返回有关如何处理被拦截请求的指令。可能有以下说明:

¥Response resolver must always return the instruction on what to do with the intercepted request. There are the following instructions possible:

使用模拟响应进行响应

¥Respond with a mocked response

要使用模拟响应响应被拦截的请求,请构造一个 Fetch API Response 实例并从响应解析器返回它。

¥To respond to an intercepted request with a mocked response, construct a Fetch API Response instance and return it from the response resolver.

import { http } from 'msw'
 
export const handlers = [
  http.get('/post/:id', ({ params }) => {
    return Response.json({
      id: params.id,
      title: 'Hello world',
    })
  }),
]

你不必导入 Response 构造函数,因为它是每个浏览器和现代版本的 Node.js(v18.0.0+)中可用的标准 Fetch API 的一部分。

¥You don’t have to import the Response constructor because it’s a part of the standard Fetch API available in every browser and in modern versions of Node.js (v18.0.0+).

为了获得更好的兼容性,我们强烈建议使用 MSW 中的 HttpResponse 类,而不是原生 Response

¥For better compatibility, we highly recommend using the HttpResponse class from MSW instead of the native Response:

HttpResponse

API reference for the `HttpResponse` class.

传递请求

¥Passthrough the request

要传递被拦截的请求(按原样执行),请从响应解析器返回 passthrough() 函数调用。

¥To passthrough the intercepted request (perform it as-is), return the passthrough() function call from the response resolver.

import { http, passthrough } from 'msw'
 
export const handlers = [
  http.get('/user', () => {
    return passthrough()
  }),
]

passthrough

Handle the intercepted request by performing it as-is.

请求失败

¥Fallthrough the request

如果响应解析器未返回任何内容,它将停止执行并告诉 MSW 继续寻找任何其他匹配的请求处理程序,这些处理程序可能会返回有关如何处理被拦截请求的指令。

¥If a response resolver returns nothing, it stops execution and tells MSW to keep looking for any other matching request handlers that may return instruction on how to handle the intercepted request.

import { http, HttpResponse } from 'msw'
 
export const handlers = [
  http.get('/user', ({ request }) => {
    // If the intercepted request has a particular
    // "Accept" header value, skip this request handler
    // and let MSW "fallthrough" to the next one.
    if (request.headers.get('Accept') === 'text/csv') {
      return
    }
 
    return HttpResponse.json({ name: 'John' })
  }),
  http.get('/user', () => {
    // Since this request handler also matches the
    // "GET /user" request, it will be used instead
    // when the "Accept" request header is "text/csv".
    return HttpResponse.text('John')
  }),
]

组合说明

¥Combining instructions

单个响应解析器可能会根据特定标准以不同的方式处理拦截的请求。

¥A single response resolver may handle the intercepted request differently based on a certain criteria.

例如,以下是如何仅当路径参数满足某个条件时才使用模拟响应进行响应,如果不满足则传递请求:

¥For example, here’s how you can respond with a mocked response only when the path parameter satisfies a certain condition, and passthrough the request if it doesn’t:

import { http, HttpResponse, passthrough } from 'msw'
 
export const handlers = [
  http.get('/user/:id', ({ params }) => {
    const { id } = params
 
    // Return a mocked response only when
    // requesting "GET /user/abc-123".
    if (id === 'abc-123') {
      return HttpResponse.json({
        id,
        name: 'John',
      })
    }
 
    // Otherwise, perform the request as-is.
    return passthrough()
  }),
]