使用开发代理进行调试

概览
目标: 在开发代理模拟 API 错误时调试应用程序
时间: 15 分钟
Plugins:GenericRandomErrorPlugin
先决条件:设置开发代理、VS Code

生成调用 API 的应用程序时,需要确保代码正确处理错误。 通过将开发代理与 Visual Studio (VS) Code 的调试器组合在一起,可以模拟 API 错误并单步执行错误处理代码,以验证它是否正常工作。

概述

使用开发代理进行调试涉及三个步骤:

  1. 配置 VS Code 以通过开发代理路由 HTTP 请求
  2. 配置开发代理以模拟特定错误
  3. 在错误处理代码和调试中设置断点

配置 VS Code 以使用开发代理进行调试

配置 VS Code 的方式取决于使用的编程语言。 以下部分演示如何为 Node.js、.NET和Python应用程序配置 VS Code。

Node.js

若要使用 Dev Proxy 调试 Node.js 应用程序,请将 launch.json 该文件配置为设置代理环境变量并禁用 TLS/SSL 证书验证。

文件: .vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug with Dev Proxy",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "program": "${workspaceFolder}/index.js",
      "env": {
        "NODE_ENV": "development",
        "http_proxy": "http://127.0.0.1:8000",
        "https_proxy": "http://127.0.0.1:8000",
        "GLOBAL_AGENT_HTTP_PROXY": "http://127.0.0.1:8000",
        "NODE_TLS_REJECT_UNAUTHORIZED": "0"
      }
    }
  ]
}

重要

该 NODE_TLS_REJECT_UNAUTHORIZED=0 设置禁用 TLS/SSL 证书验证。 仅在开发过程中使用此设置。 若要采用更安全的方式,请使用 NODE_EXTRA_CA_CERTS 直接信任 Dev Proxy 证书。 开发代理将其根证书存储为 rootCert.pfx,但 Node.js 需要 PEM 文件。 在 Dev Proxy 运行期间,使用 devproxy api token 获取 API 令牌,并将 PEM 格式的证书下载到工作区文件夹:

TOKEN=$(devproxy api token)
curl -H "Authorization: Bearer $TOKEN" -o dev-proxy-ca.pem "http://127.0.0.1:8897/proxy/rootCertificate?format=crt"

然后,将 NODE_EXTRA_CA_CERTS 指向已下载的文件:

"NODE_EXTRA_CA_CERTS": "${workspaceFolder}/dev-proxy-ca.pem"

该 GLOBAL_AGENT_HTTP_PROXY 变量由 global-agent 包使用,该包为许多 Node.js HTTP 库提供代理支持。 有关配置不同 HTTP 库的详细信息,请参阅 将 Dev Proxy 用于 Node.js 应用程序。

.NET

.NET应用程序自动使用系统代理设置。 若要使用开发代理调试.NET应用程序,通常无需设置任何环境变量。 创建基本调试配置:

文件: .vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug with Dev Proxy",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      "program": "${workspaceFolder}/bin/Debug/net8.0/MyApp.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "console": "internalConsole",
      "stopAtEntry": false
    }
  ]
}

如果应用程序未选取系统代理,请显式设置代理环境变量:

文件: .vscode/launch.json(包含显式代理设置)

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug with Dev Proxy",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      "program": "${workspaceFolder}/bin/Debug/net8.0/MyApp.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "console": "internalConsole",
      "stopAtEntry": false,
      "env": {
        "http_proxy": "http://127.0.0.1:8000",
        "https_proxy": "http://127.0.0.1:8000"
      }
    }
  ]
}

小窍门

在 Windows 和 macOS 上,如果在 Dev 代理设置期间将其安装为受信任的根证书,.NET会自动信任开发代理证书。 在 Linux 上,可能需要手动信任证书。 请参阅分发的文档,了解如何配置受信任的证书。

Python

若要使用开发代理调试Python应用程序,请将 launch.json 文件配置为设置代理环境变量。 配置取决于你使用的是 requests 库还是其他 HTTP 库。

文件: .vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug with Dev Proxy",
      "type": "debugpy",
      "request": "launch",
      "program": "${workspaceFolder}/main.py",
      "console": "integratedTerminal",
      "env": {
        "HTTP_PROXY": "http://127.0.0.1:8000",
        "HTTPS_PROXY": "http://127.0.0.1:8000",
        "REQUESTS_CA_BUNDLE": ""
      }
    }
  ]
}

重要

将 REQUESTS_CA_BUNDLE 设置为空字符串会告诉 requests 库跳过 TLS/SSL 证书验证。 仅在开发过程中使用此设置。

为了更安全的方法,将 REQUESTS_CA_BUNDLE 指向开发代理证书:

macOS/Linux:

"REQUESTS_CA_BUNDLE": "${env:HOME}/.devproxy/rootCert.pem"

Windows:

"REQUESTS_CA_BUNDLE": "${env:USERPROFILE}\\.devproxy\\rootCert.pem"

如果使用 httpx 库,请改用 TLS/SSL_CERT_FILE 环境变量配置 TLS/SSL 验证:

{
  "env": {
    "HTTP_PROXY": "http://127.0.0.1:8000",
    "HTTPS_PROXY": "http://127.0.0.1:8000",
    "TLS/SSL_CERT_FILE": "${env:HOME}/.devproxy/rootCert.pem"
  }
}

配置开发代理以模拟错误

要调试错误处理,请将开发代理配置为在应用调用 API 时返回特定错误。 使用 GenericRandomErrorPlugin 模拟类似 429 Too Many Requests 或 500 Internal Server Error 的错误。

模拟 429 (请求过多) 错误

创建一个用于模拟限速的开发代理配置文件:

文件: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v4.0.0/rc.schema.json",
  "plugins": [
    {
      "name": "GenericRandomErrorPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "errorsConfig"
    }
  ],
  "urlsToWatch": [
    "https://api.contoso.com/*"
  ],
  "errorsConfig": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v4.0.0/genericrandomerrorplugin.schema.json",
    "errorsFile": "errors.json",
    "rate": 100
  }
}

创建具有特定错误响应的错误文件:

文件: errors.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v4.0.0/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.contoso.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json"
            },
            {
              "name": "Retry-After",
              "value": "60"
            }
          ],
          "body": {
            "error": {
              "code": "TooManyRequests",
              "message": "Rate limit exceeded. Retry after 60 seconds."
            }
          }
        }
      ]
    }
  ]
}

小窍门

将 100 设置为 rate,让每个请求都失败,以便在调试过程中稳定地触发错误处理代码。 降低测试间歇性错误时的速率。

模拟 500 (内部服务器错误)

若要模拟服务器错误,请添加另一个错误响应:

文件: errors.json(多个错误)

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v4.0.0/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.contoso.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json"
            },
            {
              "name": "Retry-After",
              "value": "60"
            }
          ],
          "body": {
            "error": {
              "code": "TooManyRequests",
              "message": "Rate limit exceeded. Retry after 60 seconds."
            }
          }
        },
        {
          "statusCode": 500,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json"
            }
          ],
          "body": {
            "error": {
              "code": "InternalServerError",
              "message": "An unexpected error occurred."
            }
          }
        }
      ]
    }
  ]
}

定义多个错误响应时,开发代理会随机为每个截获的请求选择一个。

调试错误处理代码

配置 VS Code 和开发代理后,现在可以调试错误处理代码。

步骤 1:设置断点

打开源代码并在错误处理代码中设置断点。 例如,在 Node.js 应用程序中:

async function fetchData() {
  try {
    const response = await fetch('https://api.contoso.com/data');
    
    if (!response.ok) {
      // Set a breakpoint here to debug error responses
      throw new Error(`HTTP error: ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    // Set a breakpoint here to debug exceptions
    console.error('Failed to fetch data:', error);
    throw error;
  }
}

步骤 2:启动开发代理

使用您的配置文件启动 Dev 代理:

devproxy --config-file devproxyrc.json

步骤 3:开始在 VS Code 中进行调试

  1. 打开 VS Code
  2. 按 F5 或选择“运行 > 启动调试”
  3. 当应用程序进行 API 调用时,开发代理将截获它并返回错误
  4. VS Code 在断点处暂停
  5. 使用调试控件单步执行代码并检查变量

步骤 4:检查错误

当 VS Code 在断点处暂停时,使用调试面板来:

  • 查看错误响应状态代码和消息
  • 检查局部变量的值
  • 单步执行重试逻辑
  • 验证错误消息是否对用户友好

自动启动和停止开发代理

若要简化调试工作流,请将 VS Code 配置为在开始调试时自动启动开发代理,并在完成后停止它。 安装Dev Proxy Toolkit 扩展并配置任务:

文件: .vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "devproxy-start",
      "type": "devproxy",
      "command": "start",
      "args": [
        "--config-file",
        "devproxyrc.json"
      ],
      "isBackground": true,
      "problemMatcher": "$devproxy-watch"
    },
    {
      "label": "devproxy-stop",
      "type": "devproxy",
      "command": "stop"
    }
  ]
}

若要使用这些任务,请更新您的 launch.json:

文件: .vscode/launch.json(使用自动启动Node.js)

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug with Dev Proxy",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "program": "${workspaceFolder}/index.js",
      "preLaunchTask": "devproxy-start",
      "postDebugTask": "devproxy-stop",
      "env": {
        "NODE_ENV": "development",
        "http_proxy": "http://127.0.0.1:8000",
        "https_proxy": "http://127.0.0.1:8000",
        "GLOBAL_AGENT_HTTP_PROXY": "http://127.0.0.1:8000",
        "NODE_TLS_REJECT_UNAUTHORIZED": "0"
      }
    }
  ]
}

高效调试的建议

  • 若要持续命中断点,请在开发代理配置中设置 "rate": 100 ,以便每个请求都失败。
  • 若要了解代码如何处理特定错误,请在调试时使用单个错误响应。
  • 要验证你的代码遵守限制,请检查它在调试 429 错误时是否读取并遵循 Retry-After 标头。
  • 若要确保代码正常处理异常响应,请使用 Dev Proxy 模拟格式不正确的 JSON 或缺少标头等边缘情况。
  • 若要仅在特定错误时中断,请在 VS Code 中使用条件断点,方法是右键单击断点并添加如 response.status === 429 这样的条件。

另请参阅