Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
toxy — 可破解的HTTP代理,用于弹性测试和模拟网络条件 | Kitploit
工具/GitHubGitHub/h2non/toxy
漏洞分析Web代理与拦截API安全测试网络安全渗透测试混沌工程Archived
GitHubh2non/toxy

toxy

可破解的HTTP代理,用于弹性测试和模拟网络条件

查看仓库
2.7k80264年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
# toxy [![Build Status](https://api.travis-ci.org/h2non/toxy.svg?branch=master&style=flat)](https://travis-ci.org/h2non/toxy) [![Code Climate](https://codeclimate.com/github/h2non/toxy/badges/gpa.svg)](https://codeclimate.com/github/h2non/toxy) [![NPM](https://img.shields.io/npm/v/toxy.svg)](https://www.npmjs.org/package/toxy) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com)

> **当前未积极维护,可能与最新的 Node.js 运行时不兼容**。如果你有兴趣维护 toxy,请提交 issue。

**可入侵的 HTTP 代理**,用于**模拟**服务器**故障场景**、**系统弹性测试**和**意外网络状况**,专为 [node.js](http://nodejs.org) 构建。

<img align="right" height="180" src="http://s8.postimg.org/ikc9jxllh/toxic.jpg" />

它主要用于抵抗故障测试,在覆盖容错和弹性能力时特别有用,尤其是在[容忍延迟网络](https://en.wikipedia.org/wiki/Delay-tolerant_networking)和[面向服务](http://microservices.io/patterns/index.html)架构中,toxy 可以作为服务间的中间人代理来注入故障。

toxy 允许你插入[毒药](#poisons),可选择通过[规则](#rules)过滤,这些规则可以拦截并按需更改 HTTP 流,在此过程中执行多种恶意操作,例如限制带宽、延迟网络数据包、注入网络抖动延迟或回复自定义错误或状态码。

它主要在 L7 层操作,尽管可以模拟 L3 层网络条件。

toxy 可以通过[编程方式](#programmatic-api)或 [HTTP API](#http-api) 流畅使用。

它基于 [rocky](https://github.com/h2non/rocky) 构建,一个全功能的面向中间件的 HTTP 代理,并且也可以作为标准中间件[插件式](https://github.com/h2non/toxy/blob/master/examples/express.js)地用于 [connect](https://github.com/senchalabs/connect)/[express](http://expressjs.com)。

需要 node.js +4。

## 目录

- [功能特性](#features)
- [介绍](#introduction)
  - [为什么使用 toxy?](#why-toxy)
  - [概念](#concepts)
  - [工作原理](#how-it-works)
- [使用](#usage)
  - [安装](#installation)
  - [示例](#examples)
- [基准测试](#benchmark)
- [毒药](#poisons)
  - [中毒范围](#poisoning-scopes)
  - [中毒阶段](#poisoning-phases)
  - [内置毒药](#built-in-poisons)
    - [延迟](#latency)
    - [注入响应](#inject-response)
    - [带宽](#bandwidth)
    - [速率限制](#rate-limit)
    - [慢读](#slow-read)
    - [慢打开](#slow-open)
    - [慢关闭](#slow-close)
    - [节流](#throttle)
    - [中止连接](#abort-connection)
    - [超时](#timeout)
  - [如何编写毒药](#how-to-write-poisons)
- [规则](#rules)
  - [内置规则](#built-in-rules)
    - [概率](#probability)
    - [时间阈值](#time-threshold)
    - [方法](#method)
    - [内容类型](#content-type)
    - [请求头](#headers)
    - [响应头](#response-headers)
    - [请求体](#body)
    - [响应体](#response-body)
    - [响应状态](#response-status)
  - [第三方规则](#third-party-rules)
  - [如何编写规则](#how-to-write-rules)
- [编程 API](#programmatic-api)
- [HTTP API](#http-api)
  - [使用](#usage)
  - [授权](#authorization)
  - [API](#api)
  - [编程 API](#programmatic-api-1)
- [许可证](#license)

## 功能特性

- 全功能的 HTTP/S 代理(基于 [rocky](https://github.com/h2non/rocky) 和 [http-proxy](https://github.com/nodejitsu/node-http-proxy))
- 可入侵且优雅的编程 API(受 connect/express 启发)
- 用于外部管理和动态配置的管理 HTTP API
- 内置特色路由器,支持嵌套配置
- 分层且可组合的中毒机制,支持基于规则的过滤
- 分层中间件层(全局和路由范围)
- 可通过中间件轻松扩展(基于 connect/express 中间件)
- 支持入站和出站流量的中毒
- 内置毒药(带宽、错误、中止、延迟、慢读等)
- 基于规则的中毒(概率、HTTP 方法、请求头、请求体等)
- 支持第三方毒药和规则
- 通过中间件内置的负载均衡器和流量拦截器
- 继承自 [rocky](https://github.com/h2non/rocky) 的 API 和功能
- 与 connect/express(及其大部分中间件)兼容
- 可作为独立的 HTTP 代理运行

## 介绍

### 为什么使用 toxy?

市场上有一些其他类似 `toxy` 的解决方案,但大多数都没有提供合适的程序化控制,通常不易于入侵、配置,或者直接封闭于扩展性。

此外,这些解决方案中的大多数只在 TCP L3 层栈上操作,而不是提供高级抽象来覆盖 HTTP L7 协议特定领域和性质的常见需求,而 toxy 试图提供这一点。

toxy 带来了一个强大、可入侵且可扩展的解决方案,具有方便的抽象,同时没有失去适当的低级接口能力,以便轻松处理 HTTP 协议原语。

toxy 是基于组合、简单性和可扩展性原则设计的。通过其内置的分层领域特定中间件层,你可以轻松地根据自己需求扩展 toxy 的功能。

### 概念

`toxy` 引入了两个指令:毒药(poisons)和规则(rules)。

**毒药(Poisons)** 是感染入站或出站 HTTP 事务的特定逻辑(例如:注入延迟、回复错误)。一个 HTTP 事务可以被一个或多个毒药感染,并且这些毒药也可以配置为感染全局或路由级别的流量。

**规则(Rules)** 是一种匹配验证过滤器,它检查 HTTP 请求/响应,以确定给定某些规则时,HTTP 事务是否应被中毒(例如:如果请求头匹配、查询参数、方法、请求体等)。规则可以被重用并应用于入站和出站流量流,包括不同的范围:全局、路由或毒药级别。

### 工作原理```
↓  ( Incoming request )  ↓
↓          |||           ↓
↓    +-------------+     ↓
↓    | Toxy Router |     ↓ -> Match the incoming request
↓    +-------------+     ↓
↓          |||           ↓
↓ +--------------------+ ↓
↓ |   Incoming phase   | ↓ -> The proxy receives the request from the client
↓ |~~~~~~~~~~~~~~~~~~~~| ↓
↓ |  ----------------  | ↓
↓ |  |  Exec Rules  |  | ↓ -> Apply configured rules for the incoming request
↓ |  ----------------  | ↓
↓ |        |||         | ↓
↓ |  ----------------  | ↓
↓ |  | Exec Poisons |  | ↓ -> If all rules passed, then poison the HTTP flow
↓ |  ----------------  | ↓
↓ +~~~~~~~~~~~~~~~~~~~~+ ↓
↓        /      \        ↓
↓        \      /        ↓
↓ +--------------------+ ↓
↓ |  HTTP dispatcher   | ↓ -> Forward the HTTP traffic to the target server, either poisoned or not
↓ +--------------------+ ↓
↓        /      \        ↓
↓        \      /        ↓
↓ +--------------------+ ↓
↓ |   Outgoing phase   | ↓ -> Receives response from target server
↓ |~~~~~~~~~~~~~~~~~~~~| ↓
↓ |  ----------------  | ↓
↓ |  |  Exec Rules  |  | ↓ -> Apply configured rules for the outgoing request
↓ |  ----------------  | ↓
↓ |        |||         | ↓
↓ |  ----------------  | ↓
↓ |  | Exec Poisons |  | ↓ -> If all rules passed, then poison the HTTP flow before send it to the client
↓ |  ----------------  | ↓
↓ +~~~~~~~~~~~~~~~~~~~~+ ↓
↓          |||           ↓
↓ ( Send to the client ) ↓ -> Finally, send the request to the client, either poisoned or not
```
## 用法

### 安装```
npm install toxy
```
### 示例

更多用例请参见 [examples](https://github.com/h2non/toxy/tree/master/examples) 目录。```js
var toxy = require('toxy')
var poisons = toxy.poisons
var rules = toxy.rules

// Create a new toxy proxy
var proxy = toxy()

// Default server to forward incoming traffic
proxy
  .forward('http://httpbin.org')

// Register global poisons and rules
proxy
  .poison(poisons.latency({ jitter: 500 }))
  .rule(rules.probability(25))

// Register multiple routes
proxy
  .get('/download/*')
  .forward('http://files.myserver.net')
  .poison(poisons.bandwidth({ bps: 1024 }))
  .withRule(rules.headers({'Authorization': /^Bearer (.*)$/i }))

// Infect outgoing traffic only (after the server replied properly)
proxy
  .get('/image/*')
  .outgoingPoison(poisons.bandwidth({ bps: 512 }))
  .withRule(rules.method('GET'))
  .withRule(rules.timeThreshold({ duration: 1000, threshold: 1000 * 10 }))
  .withRule(rules.responseStatus({ range: [ 200, 400 ] }))

proxy
  .all('/api/*')
  .poison(poisons.rateLimit({ limit: 10, threshold: 1000 }))
  .withRule(rules.method(['POST', 'PUT', 'DELETE']))
  // And use a different more permissive poison for GET requests
  .poison(poisons.rateLimit({ limit: 50, threshold: 1000 }))
  .withRule(rules.method('GET'))

// Handle the rest of the traffic
proxy
  .all('/*')
  .poison(poisons.slowClose({ delay: 1000 }))
  .poison(poisons.slowRead({ bps: 128 }))
  .withRule(rules.probability(50))

proxy.listen(3000)
console.log('Server listening on port:', 3000)
console.log('Test it:', 'http://localhost:3000/image/jpeg')
```
## 基准测试

详情请参见 [toxy/benchmark](https://github.com/h2non/toxy/tree/master/benchmark)。

## 毒药

毒药包含特定逻辑,用于在代理服务器中拦截、变异、包装、修改和/或取消HTTP事务。
毒药可以应用于传入或传出流量,甚至两者(参见[毒化阶段](#poisoning-phases))。

毒药可以组合并复用于不同的HTTP场景。
它们按FIFO顺序异步执行。

### 毒化范围

`toxy` 具有层次化设计,基于两个不同的作用域:`global` 和 `route`。

**全局**作用域指向代理服务器接收的所有传入HTTP流量,无论HTTP方法或路径如何。

**路由**作用域指向与特定HTTP动词和URI路径匹配的任何传入流量。

毒药可以插入到两种作用域中,这意味着您可以更精确地操作并限制毒化范围,例如,您可能只想对某些路由(如 `/download` 或 `/images`)应用带宽限制毒药。

参见 [routes.js](https://github.com/h2non/toxy/blob/master/examples/routes.js) 获取示例。

### 毒化阶段

毒药可以插入到传入或传出流量中,甚至两者。

**传入**毒化在代理已接收流量但尚未转发给目标服务器时应用。

**传出**毒化指的是已转发给目标服务器的流量,并且代理收到其响应,但该响应尚未发送给客户端。

这本质上意味着,您可以在请求转发到目标HTTP服务器之前或之后,或者在发送给客户端之前或之后,插入毒药来感染HTTP流量。

这允许您根据请求或服务器响应应用更好更精确的毒化。

例如,鉴于某些毒药(如 `inject error`)的性质,您可能希望根据目标服务器响应(例如,某个标头是否存在)来启用它。

参见 [poison-phases.js](https://github.com/h2non/toxy/blob/master/examples/poison-phases.js) 获取示例。

### 内置毒药

#### Latency

<table>
<tr>
<td><b>名称</b></td><td>latency</td>
</tr>
<tr>
<td><b>毒化阶段</b></td><td>incoming / outgoing</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>true</td>
</tr>
</table>

在响应中注入延迟抖动来感染HTTP流量。

**参数**:

- **options** `object`
  - **jitter** `number` - 抖动值(毫秒)
  - **max** `number` - 随机抖动最大值
  - **min** `number` - 随机抖动最小值```js
toxy.poison(toxy.poisons.latency({ jitter: 1000 }))
// Or alternatively using a random value
toxy.poison(toxy.poisons.latency({ max: 1000, min: 100 }))
```
#### 注入响应

<table>
<tr>
<td><b>名称</b></td><td>inject</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入 / 传出</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>否(仅作为传入毒药)</td>
</tr>
</table>

在将请求发送到目标服务器之前,拦截请求并注入自定义响应。
用于注入服务器端产生的错误。

**参数**:

- **options** `object`
  - **code** `number` - 响应 HTTP 状态码。默认值 `500`
  - **headers** `object` - 可选的要发送的头部
  - **body** `mixed` - 可选的要发送的正文数据。可以是 `buffer` 或 `string`
  - **encoding** `string` - 正文编码。默认为 `utf8````js
toxy.poison(toxy.poisons.inject({
  code: 503,
  body: '{"error": "toxy injected error"}',
  headers: {'Content-Type': 'application/json'}
}))
```
#### 带宽

<table>
<tr>
<td><b>名称</b></td><td>bandwidth</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入 / 传出</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>是</td>
</tr>
</table>

限制在特定时间范围内,通过传出 HTTP 流量在网络中发送的字节数。

此毒剂基本上是 [throttle](#throttle) 的别名。

**参数**:

- **options** `object`
  - **bytes** `number` - 要发送的字节块大小。默认值 `1024`
  - **threshold** `number` - 数据包时间范围(毫秒)。默认值 `1000````js
toxy.poison(toxy.poisons.bandwidth({ bytes: 512 }))
```
#### 速率限制

<table>
<tr>
<td><b>名称</b></td><td>rateLimit</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入 / 传出</td>
</tr>
<tr>
<td><b>是否到达服务器</b></td><td>true</td>
</tr>
</table>

限制代理在特定时间窗口内接收的请求数量。旨在测试 API 限流。会暴露典型的 `X-RateLimit-*` 头。

请注意,这是一个非常简单的速率限制实现,限制存储在内存中,因此完全是易失性的。在 [npm](https://www.npmjs.com/search?q=rate+limit) 上有许多功能丰富且一致的限流器实现,你可以作为毒药插入。你可能还会对[令牌桶算法](http://en.wikipedia.org/wiki/Token_bucket)感兴趣。

**参数**:

- **options** `object`
  - **limit** `number` - 请求总数。默认为 `10`
  - **threshold** `number` - 限制时间窗口(毫秒)。默认为 `1000`
  - **message** `string` - 当达到限制时的可选错误消息。
  - **code** `number` - 达到限制时的 HTTP 状态码。默认为 `429`。```js
toxy.poison(toxy.poisons.rateLimit({ limit: 5, threshold: 10 * 1000 }))
```
#### 慢速读取

<table>
<tr>
<td><b>名称</b></td><td>slowRead</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>incoming</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>true</td>
</tr>
</table>

缓慢读取传入的有效载荷数据包。仅适用于非GET请求。

**参数**:

- **options** `object`
  - **chunk** `number` - 数据包块大小(字节)。默认为 `1024`
  - **threshold** `number` - 限制阈值时间范围(毫秒)。默认为 `1000````js
toxy.poison(toxy.poisons.slowRead({ chunk: 2048, threshold: 1000 }))
```
#### Slow open
名称:`slowOpen`

<table>
<tr>
<td><b>名称</b></td><td>slowOpen</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>是</td>
</tr>
</table>

延迟HTTP连接就绪状态。

**参数**:

- **options** `object`
  - **delay** `number` - 延迟连接的时间,以毫秒为单位。默认为 `1000````js
toxy.poison(toxy.poisons.slowOpen({ delay: 2000 }))
```
#### 缓慢关闭

<table>
<tr>
<td><b>名称</b></td><td>slowClose</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>入站 / 出站</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>true</td>
</tr>
</table>

延迟HTTP连接关闭信号(EOF)。

**参数**:

- **options** `object`
  - **delay** `number` - 延迟时间(毫秒)。默认为 `1000````js
toxy.poison(toxy.poisons.slowClose({ delay: 2000 }))
```
#### Throttle

<table>
<tr>
<td><b>名称</b></td><td>throttle</td>
</tr>
<tr>
<td><b>中毒阶段</b></td><td>传入/传出</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>是</td>
</tr>
</table>

限制在特定阈值时间帧内通过网络发送的数据包数量。

**参数**:

- **options** `object`
  - **chunk** `number` - 数据包块大小(字节)。默认为 `1024`
  - **delay** `object` - 数据块延迟时间帧(毫秒)。默认为 `100````js
toxy.poison(toxy.poisons.throttle({ chunk: 2048, threshold: 1000 }))
```
#### 中止连接

<table>
<tr>
<td><b>名称</b></td><td>abort</td>
</tr>
<tr>
<td><b>中毒阶段</b></td><td>传入/传出</td>
</tr>
<tr>
<td><b>是否到达服务器</b></td><td>false(仅作为传入中毒)</td>
</tr>
</table>

中止 TCP 连接。从底层视角来看,这将销毁服务器上的套接字,仅工作在 TCP 层面,不发送任何特定的 HTTP 应用层数据。

**参数**:

- **options** `object`
  - **delay** `number` - 在等待指定的毫秒后中止 TCP 连接。默认值为 `0`
  - **next** `boolean` - 如果为 `true`,当目标服务器响应时间超过 `delay` 参数时,连接将被中止。默认值为 `false`
  - **error** `Error` - 销毁套接字时使用的自定义 Node.js 内部错误。默认值为 `null````js
// Basic connection abort
toxy.poison(toxy.poisons.abort())
// Abort after a delay
toxy.poison(toxy.poisons.abort(1000))
// In this case, the socket will be closed if
// the target server takes more than
// 2 seconds to respond
toxy.poison(toxy.poisons.abort({ delay: 2000, next: true }))
```
#### 超时

<table>
<tr>
<td><b>名称</b></td><td>timeout</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>入站 / 出站</td>
</tr>
<tr>
<td><b>到达服务器</b></td><td>true</td>
</tr>
</table>

定义响应超时。当转发到可能较慢的服务器时很有用。

**参数**:

- **milliseconds** `number` - 超时时间(毫秒)```js
toxy.poison(toxy.poisons.timeout(5000))
```
### 如何编写毒药

毒药作为标准中间件函数实现,具有与 connect/express 中间件相同的接口。

有些毒药实现起来并非易事,因此你需要熟悉 node.js [http](https://nodejs.org/api/http.html) 模块及其 API。

以下是一个简单的服务器延迟毒药示例:```js
var toxy = require('toxy')

function customLatencyPoison (delay) {
  // We name the function since toxy uses it as identifier to get/disable/remove it in the future
  return function customLatency (req, res, next) {
    var timeout = setTimeout(process, delay)
    req.once('close', onClose)

    function onClose () {
      clearTimeout(timeout)
      next('client connection closed')
    }

    function process () {
      req.removeListener('close', onClose)
      next()
    }
  }
}

var proxy = toxy()

// Register and enable the poison
proxy
  .get('/foo')
  .poison(customLatencyPoison(2000))
```
你可以选择使用自己的恶意载荷来扩展内置的恶意载荷:```js
toxy.addPoison(customLatency)

// Then you can use it as a built-in poison
proxy
  .get('/foo')
  .poison(toxy.poisons.customLatency)
```
关于具体的真实例子,请参阅[内置投毒](https://github.com/h2non/toxy/tree/master/lib/poisons)的实现。

## 规则

规则是简单的验证过滤器,它检查传入或传出的HTTP流量,以根据规则的解析值确定当前HTTP事务是否应该被投毒。

规则有助于在不同投毒场景中组合、解耦和重用逻辑。
规则可以应用于全局、路由甚至投毒作用域,并且也适用于两个[投毒阶段](#poisoning-phases)。

规则按先进先出顺序执行。它们的评估逻辑等价于 JavaScript 中的 `Array#every()`:必须通过所有规则才能继续投毒。

### 内置规则

#### 概率

<table>
<tr>
<td><b>名称</b></td><td>概率</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入/传出</td>
</tr>
</table>

通过随机概率启用规则。用于随机投毒。

**参数**:

- **percentage** `number` - 过滤百分比。默认 `50````js
var rule = toxy.rules.probability(85)
toxy.rule(rule)
```
#### 时间阈值

<table>
<tr>
<td><b>名称</b></td><td>timeThreshold</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>incoming / outgoing</td>
</tr>
</table>

基于特定时间阈值和持续时间启用投毒的简单规则。
例如,你可以在一个时间阈值(如1分钟)内,在特定时间长度(如1秒)内启用某些投毒。

**参数**:

- **options** `object`
  - **duration** `number` - 启用时间间隔(毫秒)。默认为 `1000`
  - **threshold** `number` - 重新启用投毒前等待的时间阈值(毫秒)。默认为 `10000````js
// Enable the poisoning only 100 milliseconds per each 10 seconds
proxy.rule(toxy.rules.timeThreshold(100))
// Enable poisoning during 1 second every minute
proxy.rule(toxy.rules.timeThreshold({ duration: 1000, period: 1000 * 60 }))
```
#### 方法

<table>
<tr>
<td><b>名称</b></td><td>method</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入 / 传出</td>
</tr>
</table>

按 HTTP 方法过滤。

**参数**:

- **method** `string|array` - 要过滤的方法或方法列表。```js
var method = toxy.rules.method(['GET', 'POST'])
toxy.rule(method)
```
#### 内容类型

按内容类型标头过滤。它应该存在。

**参数**:

- **value** `string|regexp` - 要匹配的标头值。```js
var rule = toxy.rules.contentType('application/json')
toxy.rule(rule)
```
#### 请求头

<table>
<tr>
<td><b>名称</b></td><td>请求头</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>入站 / 出站</td>
</tr>
</table>

按请求头进行过滤。

**参数**:

- **headers** `object` - 通过键值对匹配的请求头。`value` 可以是字符串、正则表达式、`boolean` 或 `function(headerValue, headerName) => boolean````js
var matchHeaders = {
  'content-type': /^application/\json/i,
  'server': true, // meaning it should be present,
  'accept': function (value, key) {
    return value.indexOf('text') !== -1
  }
}

var rule = toxy.rules.headers(matchHeaders)
toxy.rule(rule)
```
#### 响应头

<table>
<tr>
<td><b>名称</b></td><td>responseHeaders</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>outgoing</td>
</tr>
</table>

按目标服务器的响应头进行过滤。与 `headers` 规则相同,但评估的是出站请求。

**参数**:

- **headers** `object` - 通过键值对匹配的头部。`value` 可以是 `string`、`regexp`、`boolean` 或 `function(headerValue, headerName) => boolean````js
var matchHeaders = {
  'content-type': /^application/\json/i,
  'server': true, // meaning it should be present,
  'accept': function (value, key) {
    return value.indexOf('text') !== -1
  }
}

var rule = toxy.rules.responseHeaders(matchHeaders)
toxy.rule(rule)
```
#### Body

<table>
<tr>
<td><b>名称</b></td><td>body</td>
</tr>
<tr>
<td><b>投毒阶段</b></td><td>传入 / 传出</td>
</tr>
</table>

通过给定的 `string`、`regexp` 或自定义过滤器 `function` 匹配传入的消息体。

此规则非常简单,对于复杂的消息体匹配(例如:根据 JSON 模式验证),您可能需要编写自己的规则。

**参数**:

- **match** `string|regexp|function` - 要匹配的消息体内容
- **limit** `string` - 可选。消息体大小限制,使用人类可读格式。例如:`5mb`
- **encoding** `string` - 消息体编码。默认值为 `utf8`
- **length** `number` - 消息体长度。默认从 `Content-Length` 头部获取```js
var rule = toxy.rules.body('"hello":"world"')
toxy.rule(rule)

// Or using a filter function returning a boolean
var rule = toxy.rules.body(function contains(body) {
  return body.indexOf('hello') !== -1
})
toxy.rule(rule)
```
#### 响应体

<table>
<tr>
<td><b>名称</b></td><td>responseBody</td>
</tr>
<tr>
<td><b>毒化阶段</b></td><td>出站</td>
</tr>
</table>

通过给定的`string`、`regexp`或自定义过滤器`function`匹配出站正文载荷。

**参数**:

- **match** `string|regexp|function` - 要匹配的正文内容
- **encoding** `string` - 正文编码。默认为`utf8`
- **length** `number` - 正文长度。默认取自`Content-Length`头部```js
var rule = toxy.rules.responseBody('"hello":"world"')
toxy.rule(rule)

// Or using a filter function returning a boolean
var rule = toxy.rules.responseBody(function contains(body) {
  return body.indexOf('hello') !== -1
})
toxy.rule(rule)
```
#### 响应状态

<table>
<tr>
<td><b>名称</b></td><td>responseStatus</td>
</tr>
<tr>
<td><b>毒化阶段</b></td><td>outgoing</td>
</tr>
</table>

评估来自目标服务器的响应状态。
仅适用于出站毒化。

**参数**:

- **range** `array` - 要匹配的状态码范围对。默认为 `[200, 300]`。
- **lower** `number` - 将状态比较为“小于”操作。默认为 `null`。
- **higher** `number` - 将状态比较为“大于”操作。默认为 `null`。
- **value** `number` - 使用严格相等比较来匹配的状态码。默认为 `null`。
- **include** `array` - 要匹配的状态码无序列表。用于指定自定义状态。默认为 `null`。```js
// Strict evaluation of the status code
toxy.rule(toxy.rules.responseBody(200))
// Using a range of valid status
toxy.rule(toxy.rules.responseBody([200, 204]))
// Using relational comparison
toxy.rule(toxy.rules.responseBody({ higher: 199, lower: 400 }))
// Custom unordered status code to match
toxy.rule(toxy.rules.responseBody({ include: [200, 204, 400, 404] }))
```
### 第三方规则

社区提供的可用第三方规则列表。欢迎提交 PR。

- [IP](https://github.com/h2non/toxy-ip) - 根据客户端 IP 地址启用/禁用毒药(支持 CIDR、子网、范围等)。

### 如何编写规则

规则是简单的中间件函数,它们异步解析出一个 `boolean` 值,用于判断在投毒时是否应忽略某个 HTTP 事务。

您的规则必须通过中间件中的 `next(err, shouldIgnore)` 函数解析出一个 `boolean` 参数,如果规则不匹配且不应施加毒药,则传递 `true` 值,从而继续执行下一个中间件堆栈。

以下是一个简单规则的示例,它匹配 HTTP 方法以判断是否:```js
var toxy = require('toxy')

function customMethodRule(matchMethod) {
  /**
   * We name the function since it's used by toxy to identify the rule to get/disable/remove it in the future
   */
  return function customMethodRule(req, res, next) {
    var shouldIgnore = req.method !== matchMethod
    next(null, shouldIgnore)
  }
}

var proxy = toxy()

// Register and enable the rule
proxy
  .get('/foo')
  .rule(customMethodRule('GET'))
  .poison(/* ... */)
```
您可以选择用您自己的规则来扩展内置规则:```js
toxy.addRule(customMethodRule)

// Then you can use it as a built-in poison
proxy
  .get('/foo')
  .rules(toxy.rules.customMethodRule)
```
有关特色真实示例,请查看内置规则 [实现](https://github.com/h2non/toxy/tree/master/lib/rules)

## 程序化 API

`toxy` API 完全构建在 [rocky API](https://github.com/h2non/rocky#programmatic-api) 之上。换句话说,您可以使用 `rocky` 原生提供的任何方法、功能和中间件层。

### toxy([ options ])

创建一个新的 `toxy` 代理。

有关支持的 `options`,请参阅 rocky [文档](https://github.com/h2non/rocky#configuration)```js
var toxy = require('toxy')

toxy({ forward: 'http://server.net', timeout: 30000 })

toxy
  .get('/foo')
  .poison(toxy.poisons.latency(1000))
  .withRule(toxy.rules.contentType('json'))
  .forward('http://foo.server')

toxy
  .post('/bar')
  .poison(toxy.poisons.bandwidth({ bps: 1024 }))
  .withRule(toxy.rules.probability(50))
  .forward('http://bar.server')

toxy
  .post('/boo')
  .outgoingPoison(toxy.poisons.bandwidth({ bps: 1024 }))
  .withRule(toxy.rules.method('GET'))
  .forward('http://boo.server')

toxy.all('/*')

toxy.listen(3000)
```
#### toxy#get(path, [ middleware... ])
返回:`ToxyRoute`

为 `GET` 方法注册一个新路由。

#### toxy#post(path, [ middleware... ])
返回:`ToxyRoute`

为 `POST` 方法注册一个新路由。

#### toxy#put(path, [ middleware... ])
返回:`ToxyRoute`

为 `PUT` 方法注册一个新路由。

#### toxy#patch(path, [ middleware... ])
返回:`ToxyRoute`

#### toxy#delete(path, [ middleware... ])
返回:`ToxyRoute`

为 `DELETE` 方法注册一个新路由。

#### toxy#head(path, [ middleware... ])
返回:`ToxyRoute`

为 `HEAD` 方法注册一个新路由。

#### toxy#all(path, [ middleware... ])
返回:`ToxyRoute`

为任意方法注册一个新路由。

#### toxy#poisons `=>` Object

暴露一个包含内置毒药(poisons)的映射。原型别名为 `toxy.poisons`

#### toxy#rules `=>` Object

暴露一个包含内置毒药的映射。原型别名为 `toxy.rules`

#### toxy#forward(url)

定义一个 URL,用于转发代理接收到的传入流量。

#### toxy#balance(urls)

转发到多个服务器并在它们之间进行负载均衡。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#programmatic-api)

#### toxy#replay(url)

定义一个新的重放服务器。
你可以多次调用此方法以定义多个重放服务器。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#programmatic-api)

#### toxy#use(middleware)

插入一个自定义中间件。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#middleware-layer).

#### toxy#useResponse(middleware)

插入一个响应传出流量中间件。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#middleware-layer).

#### toxy#useReplay(middleware)

插入一个重放流量中间件。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#middleware-layer)

#### toxy#requestBody(middleware)

拦截传入请求体。可用于即时修改请求体。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#programmatic-api)

#### toxy#responseBody(middleware)

拦截传出响应体。可用于即时修改响应体。

更多信息,请参阅 [rocky 文档](https://github.com/h2non/rocky#programmatic-api)

#### toxy#middleware()

返回一个标准中间件,用于与 connect/express 配合使用。

#### toxy#host(host)

用自定义值覆盖 `Host` 头。类似 `forwardHost` 选项。

#### toxy#redirect(url)

将流量重定向到给定的 URL。

#### toxy#findRoute(routeIdOrPath, [ method ])

通过路由 ID 或路径及方法查找路由。

#### toxy#listen(port)

启动内置 HTTP 服务器,监听特定 TCP 端口。

#### toxy#close([ callback ])

关闭 HTTP 服务器。

#### toxy#poison(poison)
别名:`usePoison`, `useIncomingPoison`

注册一个新的毒药,用于感染 [传入](#poisoning-phases) 流量。

#### toxy#outgoingPoison(poison)
别名:`useOutgoingPoison`, `responsePoison`

注册一个新的毒药,用于感染 [传出](#poisoning-phases) 流量。

#### toxy#rule(rule)
别名:`useRule`

注册一个新规则。

#### toxy#withRule(rule)
别名:`ifRule`, `whenRule`, `poisonRule`, `poisonFilter`

为最近注册的毒药应用一个新规则。

#### toxy#enable(poison)

通过名称标识符启用一个毒药。

#### toxy#disable(poison)

通过名称标识符禁用一个毒药。

#### toxy#remove(poison)
返回:`boolean`

通过名称标识符或对象引用移除一个传入流量毒药。

#### toxy#removeOutgoing(poison)
返回:`boolean`

通过名称标识符或对象引用移除一个传出流量毒药。

#### toxy#isEnabled(poison)
返回:`boolean`

通过名称标识符检查毒药是否已启用。

#### toxy#disableAll()
别名:`disablePoisons`

禁用所有已注册的毒药。

#### toxy#getPoison(name)
返回:`Directive|null`

在栈中通过名称标识符搜索并获取已注册的毒药。

#### toxy#getIncomingPoison(name)
返回:`Directive|null`

在栈中通过名称标识符搜索并获取已注册的 `incoming` 毒药。

#### toxy#getOutgoingPoison(name)
返回:`Directive|null`

在栈中通过名称标识符搜索并获取已注册的 `outgoing` 毒药。

#### toxy#getPoisons()
返回:`array<Directive>`

返回已注册毒药的数组。

#### toxy#getIncomingPoisons()
返回:`array<Directive>`

返回已注册 `incoming` 毒药的数组。

#### toxy#getOutgoingPoisons()
返回:`array<Directive>`

返回已注册 `outgoing` 毒药的数组。

#### toxy#flush()
别名:`flushPoisons`

移除所有已注册的传入和传出流量毒药。

#### toxy#enableRule(rule)

通过名称标识符启用一个规则。

#### toxy#disableRule(rule)

通过名称标识符禁用一个规则。

#### toxy#removeRule(rule)
返回:`boolean`

通过名称标识符移除一个规则。

#### toxy#disableRules()

禁用所有已注册的规则。

#### toxy#isRuleEnabled(rule)
返回:`boolean`

通过名称标识符检查给定规则是否已启用。

#### toxy#getRule(rule)
返回:`Directive|null`

在栈中通过名称标识符搜索并获取已注册的规则。

#### toxy#getRules()
返回:`array<Directive>`

返回以 `Directive` 包装的已注册规则的数组。

#### toxy#flushRules()

移除所有规则。

### toxy.addPoison(name, fn)

扩展内置毒药。

### toxy.addRule(name, fn)

扩展内置规则。

### toxy.poisons `=>` Object

暴露一个包含内置毒药的映射。

### toxy.rules `=>` Object

暴露一个包含内置规则的映射。

### toxy.VERSION `=>` String

当前 toxy 的语义化版本。

### ToxyRoute

`ToxyRoute` 暴露与 `Toxy` 全局接口相同的接口,只是额外添加了一些路由级别的 [附加方法](https://github.com/h2non/rocky#routepath)。

你对 `ToxyRoute` API 执行的后续操作仅适用于路由级别(嵌套)。换句话说:你已经了解该 API。

这个例子可能会澄清可能的疑问:```js
var toxy = require('toxy')
var proxy = toxy()

// Now using the global API
proxy
  .forward('http://server.net')
  .poison(toxy.poisons.bandwidth({ bps: 1024 }))
  .rule(toxy.rules.method('GET'))

// Now create a route
var route = proxy
  .get('/foo')
  .toPath('/bar') // Route-level API method
  .host('server.net') // Route-level API method
  .forward('http://new.server.net')

// Now using the ToxyRoute interface
route
  .poison(toxy.poisons.bandwidth({ bps: 512 }))
  .rule(toxy.rules.contentType('json'))
```
### Directive(middlewareFn)

一个便捷的包装器,内部用于毒药(poisons)和规则(rules)。

通常情况下你不需要了解这个接口,但对于黑客目的或更底层的操作可能很有用。

#### Directive#enable()
返回值:`boolean`

#### Directive#disable()
返回值:`boolean`

#### Directive#isEnabled()
返回值:`boolean`

#### Directive#rule(rule)
别名:`filter`

#### Directive#handler()
返回值:`function(req, res, next)`

## HTTP API

`toxy` 的 HTTP API 遵循 [JSON API](http://jsonapi.org) 约定,包括基于资源的超媒体链接。

### 用法

关于特色用例,请参阅 [admin server](https://github.com/h2non/toxy/blob/master/examples/admin.js) 示例。```js
const toxy = require('toxy')

// Create the toxy admin server
var admin = toxy.admin({ cors: true })
admin.listen(9000)

// Create the toxy proxy
var proxy = toxy()
proxy.listen(3000)

// Add the toxy instance to be managed by the admin server
admin.manage(proxy)

// Then configure the proxy
proxy
  .forward('http://my.target.net')

proxy
  .get('/slow')
  .poison(toxy.poisons.bandwidth({ bps: 1024 }))

// Handle the rest of the traffic
proxy
  .all('/*')
  .poison(toxy.poisons.bandwidth({ bps: 1024 * 5 }))

console.log('toxy proxy listening on port:', 3000)
console.log('toxy admin server listening on port:', 9000)
```
有关管理程序化API的更多详情,请参见[下文](#programmatic-api-1)。

### 授权

HTTP API 可防范未授权客户端的访问。
授权客户端必须通过 `API-Key` 或 `Authorization` HTTP 标头定义 API 密钥令牌。

要启用此功能,您只需将以下选项传递给 `toxy` 管理服务器:```js
const toxy = require('toxy')

const opts = { apiKey: 's3cr3t' }
var admin = toxy.admin(opts)

admin.listen(9000)
console.log('protected toxy admin server listening on port:', 9000)
```
### API

**层次结构**:

- **服务器** - 托管的 `toxy` 实例
  - **规则** - 全局应用的规则
  - **毒药** - 全局应用的毒药
    - **规则** - 毒药特定的规则
  - **路由** - 已配置路由的列表
    - **路由** - 每个特定路由的对象
      - **规则** - 路由级别注册的规则
      - **毒药** - 路由级别注册的毒药
        - **规则** - 路由级别毒药特定的规则

#### GET /

### 服务器

#### GET /servers

#### GET /servers/:id

### 规则

#### GET /servers/:id/rules

#### POST /servers/:id/rules
**接受**:`application/json`

示例载荷:```js
{
  "name": "method",
  "options": "GET"
}
```
#### DELETE /servers/:id/rules

#### GET /servers/:id/rules/:id

#### DELETE /servers/:id/rules/:id

### 毒化

#### GET /servers/:id/poison

#### POST /servers/:id/poisons
接受:`application/json`

示例负载:```js
{
  "name": "latency",
  "phase": "outgoing",
  "options": { "jitter": 1000 }
}
```
#### DELETE /servers/:id/poisons

#### GET /servers/:id/poisons/:id

#### DELETE /servers/:id/poisons/:id

#### GET /servers/:id/poisons/:id/rules

#### POST /servers/:id/poisons/:id/rules
接受: `application/json`

示例负载:```js
{
  "name": "method",
  "options": "GET"
}
```
#### 删除 /servers/:id/poisons/:id/rules

#### 获取 /servers/:id/poisons/:id/rules/:id

#### 删除 /servers/:id/poisons/:id/rules/:id

### 路由

#### 获取 /servers/:id/routes

#### 新增 /servers/:id/routes
接受: `application/json`

示例负载:```js
{
  "path": "/foo", // Required
  "method": "GET", // use ALL for all the methods
  "forward": "http://my.server", // Optional custom forward server URL
}
```
#### DELETE /servers/:id/routes

#### GET /servers/:id/routes/:id

#### DELETE /servers/:id/routes/:id

### 路由规则

#### GET /servers/:id/routes/:id/rules

#### POST /servers/:id/routes/:id/rules
接受:`application/json`

示例负载:```js
{
  "name": "method",
  "options": "GET"
}
```
#### DELETE /servers/:id/routes/:id/rules

#### GET /servers/:id/routes/:id/rules/:id

#### DELETE /servers/:id/routes/:id/rules/:id

### 路由毒化

#### GET /servers/:id/routes/:id/poisons

#### POST /servers/:id/routes/:id/poisons
接受:`application/json`

示例负载:```js
{
  "name": "latency",
  "phase": "outgoing",
  "options": { "jitter": 1000 }
}
```
#### DELETE /servers/:id/routes/:id/poisons

#### GET /servers/:id/routes/:id/poisons/:id

#### DELETE /servers/:id/routes/:id/poisons/:id

#### GET /servers/:id/routes/:id/poisons/:id/rules

#### POST /servers/:id/routes/:id/poisons/:id/rules

接受: `application/json`

示例载荷:```js
{
  "name": "method",
  "options": "GET"
}
```
#### DELETE /servers/:id/routes/:id/poisons/:id/rules

#### GET /servers/:id/routes/:id/poisons/:id/rules/:id

#### DELETE /servers/:id/routes/:id/poisons/:id/rules/:id

### 编程接口

内置的HTTP管理服务器还提供了一个简单的接口,用于扩展和定制。例如,你可以向管理服务器添加额外的中间件,或注册新的路由。

#### toxy.admin([ opts ])
返回:`Admin`

**支持的选项**:

- **apiKey** `string` - 保护服务器的可选API密钥
- **port** `number` - 可选。监听的TCP端口
- **cors** `boolean` - 启用CORS以便浏览器访问
- **middleware** `array<function>` - 插入额外的中间件
- **ssl** `object` - Node.js HTTPS服务器的[TLS选项](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener)

##### Admin#listen([ port, host ])

开始在网络中监听。

##### Admin#manage(toxy)

管理一个`toxy`服务器实例。

##### Admin#find(toxy)

查找一个toxy实例。接受toxy服务器ID或toxy实例。

##### Admin#remove(toxy)

停止管理一个toxy实例。

##### Admin#use(...middleware)

注册一个中间件。

##### Admin#param(...middleware)

注册一个参数中间件。

##### Admin#get(path, [ ...middleware ])

注册一个GET路由。

##### Admin#post(path, [ ...middleware ])

注册一个POST路由。

##### Admin#put(path, [ ...middleware ])

注册一个PUT路由。

##### Admin#delete(path, [ ...middleware ])

注册一个DELETE路由。

##### Admin#patch(path, [ ...middleware ])

注册一个PATCH路由。

##### Admin#all(path, [ ...middleware ])

注册一个接受任何HTTP方法的路由。

##### Admin#middleware(req, res, next)

与connect/express一起使用的中间件。

##### Admin#close(cb)

停止服务器。

## 许可证

MIT - Tomas Aparicio

[![views](https://sourcegraph.com/api/repos/github.com/h2non/toxy/.counters/views.svg)](https://sourcegraph.com/github.com/h2non/toxy)
下载工具