当前未积极维护,可能与最新的 Node.js 运行时不兼容。如果你有兴趣维护 toxy,请提交 issue。
可入侵的 HTTP 代理,用于模拟服务器故障场景、系统弹性测试和意外网络状况,专为 node.js 构建。
它主要用于抵抗故障测试,在覆盖容错和弹性能力时特别有用,尤其是在容忍延迟网络和面向服务架构中,toxy 可以作为服务间的中间人代理来注入故障。
toxy 允许你插入毒药,可选择通过规则过滤,这些规则可以拦截并按需更改 HTTP 流,在此过程中执行多种恶意操作,例如限制带宽、延迟网络数据包、注入网络抖动延迟或回复自定义错误或状态码。
它主要在 L7 层操作,尽管可以模拟 L3 层网络条件。
它基于 rocky 构建,一个全功能的面向中间件的 HTTP 代理,并且也可以作为标准中间件插件式地用于 connect/express。
需要 node.js +4。
市场上有一些其他类似 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 目录。```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流量。
**参数**: