
Proxy HTTP hackable pour les tests de résilience et les conditions réseau simulées.
Pas activement maintenu, peut ne pas fonctionner avec les dernières versions de node.js. Si vous êtes intéressé par la maintenance de toxy, veuillez ouvrir une issue.
Proxy HTTP personnalisable pour simuler des scénarios de défaillance de serveur, des tests de résilience de systèmes et des conditions réseau inattendues, construit pour node.js.
Il a été principalement conçu pour les tests de résistance aux pannes, où toxy devient particulièrement utile pour couvrir les capacités de tolérance aux pannes et de résilience d'un système, en particulier dans les réseaux tolérants aux perturbations et les architectures orientées services, où toxy peut agir en tant que proxy MitM entre les services afin d'injecter des pannes.
toxy vous permet de brancher des poisons, éventuellement filtrés par des règles, qui peuvent essentiellement intercepter et modifier le flux HTTP selon vos besoins, en effectuant plusieurs actions malveillantes au milieu de ce processus, telles que limiter la bande passante, retarder les paquets réseau, injecter de la latence de gigue réseau ou répondre avec une erreur ou un code de statut personnalisé. Il opère principalement au niveau L7, bien qu'il puisse simuler des conditions de réseau L3.
toxy peut être utilisé de manière fluide par programmation ou via l'API HTTP. Il a été construit sur la base de rocky, un proxy HTTP complet orienté middleware, et il est également intégrable dans connect/express en tant que middleware standard.
Nécessite node.js +4.
Il existe d'autres solutions similaires à toxy sur le marché, mais la plupart d'entre elles n'offrent pas un contrôle programmatique approprié et ne sont généralement pas faciles à personnaliser, configurer ou sont directement fermées à l'extensibilité.
De plus, la majorité de ces solutions fonctionnent uniquement au niveau de la pile TCP L3 au lieu de fournir des abstractions de haut niveau pour couvrir les exigences courantes dans le domaine spécifique et la nature du protocole HTTP L7, comme toxy tente de le faire.
toxy apporte une solution puissante, personnalisable et extensible avec une abstraction pratique, mais sans perdre les capacités d'interface de bas niveau appropriées pour traiter facilement les primitives du protocole HTTP.
toxy a été conçu selon les règles de composition, de simplicité et d'extensibilité. Grâce à sa couche middleware hiérarchique spécifique au domaine intégrée, vous pouvez facilement étendre les fonctionnalités de toxy selon vos besoins.
toxy introduit deux directives : les poisons et les règles.
Les poisons sont la logique spécifique qui infecte une transaction HTTP entrante ou sortante (par exemple : injecter une latence, répondre avec une erreur). Une transaction HTTP peut être empoisonnée par un ou plusieurs poisons, et ces poisons peuvent également être configurés pour infecter le trafic au niveau global ou de la route.
Les règles sont une sorte de filtres de validation de correspondance qui inspectent une requête/réponse HTTP afin de déterminer, selon certaines règles, si la transaction HTTP doit être empoisonnée ou non (par exemple : si les en-têtes correspondent, les paramètres de requête, la méthode, le corps...). Les règles peuvent être réutilisées et appliquées aux flux de trafic entrants et sortants, y compris à différentes portées : globale, de route ou de poison.
↓ ( 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
## Utilisation
### Installation```
npm install toxy
Voir le répertoire examples pour plus de cas d'utilisation.```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')
## Benchmark
See [toxy/benchmark](https://github.com/h2non/toxy/tree/master/benchmark) for details.
## Poisons
Poisons host specific logic which intercepts and mutates, wraps, modify and/or cancel an HTTP transaction in the proxy server.
Poisons can be applied to incoming or outgoing, or even both traffic flows (see [poison phases](#poisoning-phases)).
Poisons can be composed and reused for different HTTP scenarios.
They are executed in FIFO order and asynchronously.
### Poisoning scopes
`toxy` a une conception hiérarchique basée sur deux portées différentes : `global` et `route`.
La portée **Global** fait référence à tout le trafic HTTP entrant reçu par le serveur proxy, indépendamment de la méthode HTTP ou du chemin.
La portée **Route** fait référence à tout trafic entrant correspondant à un verbe HTTP et un chemin URI spécifiques.
Les poisons peuvent être branchés sur les deux portées, ce qui signifie que vous pouvez opérer avec une meilleure précision et restreindre la portée de l'empoisonnement. Par exemple, vous pourriez vouloir appliquer un empoisonnement de limite de bande passante uniquement à certaines routes, telles que `/download` ou `/images`.
See [routes.js](https://github.com/h2non/toxy/blob/master/examples/routes.js) for a featured example.
### Poisoning phases
Les poisons peuvent être branchés sur les flux de trafic entrants ou sortants, ou même les deux.
L'empoisonnement **entrant** est appliqué lorsque le trafic a été reçu par le proxy mais n'a pas encore été transmis au serveur cible.
L'empoisonnement **sortant** fait référence au trafic qui a été transmis au serveur cible et lorsque le proxy reçoit la réponse de celui-ci, mais que cette réponse n'a pas encore été envoyée au client.
Cela signifie, essentiellement, que vous pouvez brancher vos poisons pour infecter le trafic HTTP avant ou après que la requête soit transférée au serveur HTTP cible ou envoyée au client.
Cela vous permet d'appliquer un empoisonnement meilleur et plus précis basé sur la requête ou la réponse du serveur. Par exemple, étant donné la nature de certains poisons, comme `inject error`, vous pouvez vouloir l'activer selon la réponse du serveur cible (par exemple : la présence ou non d'un en-tête).
See [poison-phases.js](https://github.com/h2non/toxy/blob/master/examples/poison-phases.js) for a featured example.
### Built-in poisons
#### Latency
<table>
<tr>
<td><b>Nom</b></td><td>latency</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>incoming / outgoing</td>
</tr>
<tr>
<td><b>Atteint le serveur</b></td><td>true</td>
</tr>
</table>
Infecte le flux HTTP en injectant une gigue de latence dans la réponse
**Arguments** :
- **options** `object`
- **jitter** `number` - Valeur de gigue en millisecondes
- **max** `number` - Valeur maximale de gigue aléatoire
- **min** `number` - Valeur minimale de gigue aléatoire```js
toxy.poison(toxy.poisons.latency({ jitter: 1000 }))
// Or alternatively using a random value
toxy.poison(toxy.poisons.latency({ max: 1000, min: 100 }))
| Nom | inject |
| Phase d'empoisonnement | entrant / sortant |
| Atteint le serveur | false (uniquement comme poison entrant) |
Injecte une réponse personnalisée, en interceptant la requête avant de l'envoyer au serveur cible. Utile pour injecter des erreurs provenant du serveur.
Arguments:
object
number - Code de statut HTTP de la réponse. Par défaut 500object - En-têtes optionnels à envoyermixed - Données de corps optionnelles à envoyer. Il peut s'agir d'un buffer ou d'une stringstring - Encodage du corps. Par défaut `utf8````js
toxy.poison(toxy.poisons.inject({
code: 503,
body: '{"error": "toxy injected error"}',
headers: {'Content-Type': 'application/json'}
}))#### Bande passante
<table>
<tr>
<td><b>Nom</b></td><td>bandwidth</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>entrante / sortante</td>
</tr>
<tr>
<td><b>Atteint le serveur</b></td><td>true</td>
</tr>
</table>
Limite la quantité d'octets envoyés sur le réseau dans le trafic HTTP sortant pour une période donnée.
Ce poison est essentiellement un alias de [throttle](#throttle).
**Arguments** :
- **options** `object`
- **bytes** `number` - Quantité de morceau d'octets à envoyer. Par défaut `1024`
- **threshold** `number` - Fenêtre temporelle des paquets en millisecondes. Par défaut `1000````js
toxy.poison(toxy.poisons.bandwidth({ bytes: 512 }))
| Nom | rateLimit |
| Phase d'empoisonnement | entrant / sortant |
| Atteint le serveur | true |
Limite le nombre de requêtes reçues par le proxy dans une période de temps définie. Conçu pour tester les limites d'API. Expose les en-têtes typiques X-RateLimit-*.
Notez qu'il s'agit d'une implémentation très simple de limite de débit. En effet, les limites sont stockées en mémoire, elles sont donc totalement volatiles. Il existe de nombreuses implémentations complètes et cohérentes de limiteurs de débit sur npm que vous pouvez brancher en tant que poison. Vous pourriez également être intéressé par l'algorithme du seau à jetons.
Arguments :
object
number - Nombre total de requêtes. Par défaut 10number - Période de temps limite en millisecondes. Par défaut 1000string - Message d'erreur optionnel lorsque la limite est atteinte.number - Code de statut HTTP lorsque la limite est atteinte. Par défaut 429.```js
toxy.poison(toxy.poisons.rateLimit({ limit: 5, threshold: 10 * 1000 }))#### Lecture lente
<table>
<tr>
<td><b>Name</b></td><td>slowRead</td>
</tr>
<tr>
<td><b>Poisoning Phase</b></td><td>incoming</td>
</tr>
<tr>
<td><b>Reaches the server</b></td><td>true</td>
</tr>
</table>
Lit lentement les paquets de données de charge utile entrants. Valable uniquement pour les requêtes non GET.
**Arguments**:
- **options** `object`
- **chunk** `number` - Taille de morceau de paquet en octets. Par défaut `1024`
- **threshold** `number` - Limite du délai en millisecondes. Par défaut `1000````js
toxy.poison(toxy.poisons.slowRead({ chunk: 2048, threshold: 1000 }))
Nom : slowOpen
| Nom | slowOpen |
| Phase d'empoisonnement | incoming |
| Atteint le serveur | true |
Retarde l'état de préparation de la connexion HTTP.
Arguments :
object
number - Délai de connexion en millisecondes. Par défaut `1000````js
toxy.poison(toxy.poisons.slowOpen({ delay: 2000 }))#### Slow close
<table>
<tr>
<td><b>Nom</b></td><td>slowClose</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>incoming / outgoing</td>
</tr>
<tr>
<td><b>Atteint le serveur</b></td><td>true</td>
</tr>
</table>
Retarde le signal de fermeture de connexion HTTP (EOF).
**Arguments** :
- **options** `object`
- **delay** `number` - Temps de retard en millisecondes. Valeur par défaut : `1000````js
toxy.poison(toxy.poisons.slowClose({ delay: 2000 }))
| Nom | throttle |
| Phase d'empoisonnement | entrant / sortant |
| Atteint le serveur | true |
Limite la quantité de paquets envoyés sur le réseau dans un intervalle de temps seuil spécifique.
Arguments :
object
number - Taille du bloc de paquets en octets. Par défaut 1024object - Délai du bloc de données en millisecondes. Par défaut `100````js
toxy.poison(toxy.poisons.throttle({ chunk: 2048, threshold: 1000 }))#### Abort connection
<table>
<tr>
<td><b>Nom</b></td><td>abort</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>entrant / sortant</td>
</tr>
<tr>
<td><b>Atteint le serveur</b></td><td>false (seulement comme poison entrant)</td>
</tr>
</table>
Abandonne la connexion TCP. D'un point de vue bas niveau, cela détruit le socket sur le serveur, opérant uniquement au niveau TCP sans envoyer de données spécifiques au niveau applicatif HTTP.
**Arguments** :
- **options** `object`
- **delay** `number` - Abandonne la connexion TCP après avoir attendu le nombre de millisecondes donné. Par défaut `0`
- **next** `boolean` - Si `true`, la connexion sera abandonnée si le serveur cible met plus de temps que le paramètre `delay` pour répondre. Par défaut `false`
- **error** `Error` - Erreur interne personnalisée de node.js à utiliser lors de la destruction du socket. Par défaut `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 }))
| Name | timeout |
| Poisoning Phase | entrant / sortant |
| Atteint le serveur | true |
Définit un délai d'attente de réponse. Utile lors du transfert vers des serveurs potentiellement lents.
Arguments :
number - Limite de délai d'attente en millisecondes```js
toxy.poison(toxy.poisons.timeout(5000))### Comment écrire des poisons
Les poisons sont implémentés en tant que fonctions middleware standard avec la même interface que le middleware connect/express.
Certains poisons ne sont pas triviaux à implémenter, vous devez donc être familier avec le module [http](https://nodejs.org/api/http.html) de node.js et son API.
Voici un exemple simple d'un poison de latence serveur :```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))
Vous pouvez éventuellement étendre les poisons intégrés avec vos propres poisons :```js toxy.addPoison(customLatency)
// Then you can use it as a built-in poison proxy .get('/foo') .poison(toxy.poisons.customLatency)
Pour un exemple concret, jetez un œil à l'implémentation des [poisons intégrés](https://github.com/h2non/toxy/tree/master/lib/poisons).
## Rules
Les règles sont des filtres de validation simples qui inspectent le trafic HTTP entrant ou sortant afin de déterminer, étant donné certaines règles (par exemple : correspond à la méthode, aux en-têtes, aux paramètres de requête, au corps...), si la transaction HTTP en cours doit être empoisonnée ou non, en fonction de la valeur de résolution de la règle.
Les règles sont utiles pour composer, découpler et réutiliser la logique entre différents scénarios d'empoisonnement.
Les règles peuvent être appliquées à la portée globale, de route ou même d'empoisonnement, et cela s'applique également aux deux [phases d'empoisonnement](#poisoning-phases).
Les règles sont exécutées dans l'ordre FIFO. Leur logique d'évaluation est équivalente à `Array#every()` en JavaScript : toutes les règles doivent être satisfaites pour procéder à l'empoisonnement.
### Règles intégrées
#### Probability
<table>
<tr>
<td><b>Nom</b></td><td>probability</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>entrant / sortant</td>
</tr>
</table>
Active la règle de manière probabiliste aléatoire. Utile pour un empoisonnement aléatoire.
**Arguments** :
- **percentage** `number` - Pourcentage de filtrage. Par défaut `50````js
var rule = toxy.rules.probability(85)
toxy.rule(rule)
| Nom | timeThreshold |
| Phase de poison | incoming / outgoing |
Règle simple pour activer des poisons en fonction d'un seuil de temps et d'une durée spécifiques. Par exemple, vous pouvez activer certains poisons pendant une durée spécifique (ex: 1 seconde) dans un seuil de temps (ex: 1 minute).
Arguments:
object
number - Intervalle d'activation en millisecondes. Par défaut 1000number - Seuil de temps en millisecondes à attendre avant de réactiver le poison. Par défaut `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 }))#### Méthode
<table>
<tr>
<td><b>Nom</b></td><td>method</td>
</tr>
<tr>
<td><b>Phase d'empoisonnement</b></td><td>entrant / sortant</td>
</tr>
</table>
Filtre par méthode HTTP.
**Arguments**:
- **method** `string|array` - Méthode ou méthodes à filtrer.```js
var method = toxy.rules.method(['GET', 'POST'])
toxy.rule(method)
Filtre par l'en-tête de type de contenu. Il doit être présent.
Arguments :
string|regexp - Valeur d'en-tête à faire correspondre.```js
var rule = toxy.rules.contentType('application/json')
toxy.rule(rule)#### Headers
<table>
<tr>
<td><b>Nom</b></td><td>headers</td>
</tr>
<tr>
<td><b>Phase de poison</b></td><td>entrant / sortant</td>
</tr>
</table>
Filtrer par en-têtes de requête.
**Arguments** :
- **headers** `object` - En-têtes à faire correspondre par paire clé-valeur. `value` peut être une chaîne, une expression régulière, un `boolean` ou une `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)
| Nom | responseHeaders |
| Phase d'empoisonnement | sortant |
Filtrer par les en-têtes de réponse du serveur cible. Identique à la règle headers, mais évalue la requête sortante.
Arguments :
object - En-têtes à faire correspondre par paire clé-valeur. value peut être une string, regexp, boolean ou `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>Name</b></td><td>body</td>
</tr>
<tr>
<td><b>Poison Phase</b></td><td>incoming / outgoing</td>
</tr>
</table>
Correspondre à la charge utile du corps entrant par une `string`, `regexp` ou une `function` de filtre personnalisée.
Cette règle est assez simple, donc pour une correspondance complexe du corps (par exemple : validation par rapport à un schéma JSON), vous devriez probablement écrire votre propre règle.
**Arguments** :
- **match** `string|regexp|function` - Contenu du corps à faire correspondre
- **limit** `string` - Optionnel. Limite du corps en taille humaine. Ex. : `5mb`
- **encoding** `string` - Encodage du corps. Par défaut à `utf8`
- **length** `number` - Longueur du corps. Par défaut extraite de l'en-tête `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)
| Nom | responseBody |
| Phase d'empoisonnement | outgoing |
Correspond à la charge utile du corps sortant selon une string, regexp ou function de filtre personnalisée.
Arguments :
string|regexp|function – Contenu du corps à faire correspondrestring – Encodage du corps. Valeur par défaut : utf8number – Longueur du corps. Valeur par défaut extraite de l'en-tête `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)
#### Statut de la réponse
<table>
<tr>
<td><b>Nom</b></td><td>responseStatus</td>
</tr>
<tr>
<td><b>Phase de poison</b></td><td>outgoing</td>
</tr>
</table>
Évalue le statut de la réponse du serveur cible.
Applicable uniquement aux poisons sortants.
**Arguments** :
- **range** `array` - Paire de codes de statut à faire correspondre. Par défaut `[200, 300]`.
- **lower** `number` - Compare le statut comme une opération `inférieur à`. Par défaut `null`.
- **higher** `number` - Compare le statut comme une opération `supérieur à`. Par défaut `null`.
- **value** `number` - Code de statut à faire correspondre via une comparaison d'égalité stricte. Par défaut `null`.
- **include** `array` - Liste non ordonnée de codes de statut à faire correspondre. Utile pour spécifier un statut personnalisé. Par défaut `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] }))
Liste des règles tierces disponibles fournies par la communauté. Les PR sont les bienvenues.
Les règles sont de simples fonctions middleware qui se résolvent de manière asynchrone avec une valeur boolean pour déterminer si une transaction HTTP donnée doit être ignorée lors de l'empoisonnement.
Votre règle doit se résoudre avec un paramètre boolean en appelant la fonction next(err, shouldIgnore) dans le middleware, en passant une valeur true si la règle n'a pas de correspondance et ne doit pas appliquer l'empoisonnement, et donc continuer avec la prochaine pile middleware.
Voici un exemple d'une règle simple correspondant à la méthode HTTP pour déterminer si :```js var toxy = require('toxy')
function customMethodRule(matchMethod) { /**
var proxy = toxy()
// Register and enable the rule proxy .get('/foo') .rule(customMethodRule('GET')) .poison(/* ... */)
Vous pouvez éventuellement étendre les règles intégrées avec vos propres règles :```js
toxy.addRule(customMethodRule)
// Then you can use it as a built-in poison
proxy
.get('/foo')
.rules(toxy.rules.customMethodRule)
Pour des exemples concrets, jetez un œil aux règles intégrées implémentation
L'API de toxy est entièrement construite au-dessus de l'API rocky. En d'autres termes, vous pouvez utiliser toutes les méthodes, fonctionnalités et couches middleware fournies nativement par rocky.
Créez un nouveau proxy toxy.
Pour les options prises en charge, veuillez consulter la documentation de rocky.```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... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour la méthode `GET`.
#### toxy#post(path, [ middleware... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour la méthode `POST`.
#### toxy#put(path, [ middleware... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour la méthode `PUT`.
#### toxy#patch(path, [ middleware... ])
Retour: `ToxyRoute`
#### toxy#delete(path, [ middleware... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour la méthode `DELETE`.
#### toxy#head(path, [ middleware... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour la méthode `HEAD`.
#### toxy#all(path, [ middleware... ])
Retour: `ToxyRoute`
Enregistre une nouvelle route pour toute méthode.
#### toxy#poisons `=>` Object
Expose une carte des poisons intégrés. Alias de prototype vers `toxy.poisons`
#### toxy#rules `=>` Object
Expose une carte des poisons intégrés. Alias de prototype vers `toxy.rules`
#### toxy#forward(url)
Définit une URL pour transférer le trafic entrant reçu par le proxy.
#### toxy#balance(urls)
Transfère vers plusieurs serveurs en équilibrant la charge.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#programmatic-api)
#### toxy#replay(url)
Définit un nouveau serveur de rejeu.
Vous pouvez appeler cette méthode plusieurs fois pour définir plusieurs serveurs de rejeu.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#programmatic-api)
#### toxy#use(middleware)
Insère un middleware personnalisé.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#middleware-layer).
#### toxy#useResponse(middleware)
Insère un middleware pour le trafic sortant.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#middleware-layer).
#### toxy#useReplay(middleware)
Insère un middleware pour le trafic de rejeu.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#middleware-layer)
#### toxy#requestBody(middleware)
Intercepte le corps de la requête entrante. Utile pour le modifier à la volée.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#programmatic-api)
#### toxy#responseBody(middleware)
Intercepte le corps de la réponse sortante. Utile pour le modifier à la volée.
Pour plus d'informations, consultez la [documentation rocky](https://github.com/h2non/rocky#programmatic-api)
#### toxy#middleware()
Retourne un middleware standard à utiliser avec connect/express.
#### toxy#host(host)
Remplace l'en-tête `Host` par une valeur personnalisée. Similaire à l'option `forwardHost`.
#### toxy#redirect(url)
Redirige le trafic vers l'URL donnée.
#### toxy#findRoute(routeIdOrPath, [ method ])
Recherche une route par ID ou chemin et méthode.
#### toxy#listen(port)
Démarre le serveur HTTP intégré, en écoutant sur un port TCP spécifique.
#### toxy#close([ callback ])
Ferme le serveur HTTP.
#### toxy#poison(poison)
Alias: `usePoison`, `useIncomingPoison`
Enregistre un nouveau poison pour infecter le trafic [entrant](#poisoning-phases).
#### toxy#outgoingPoison(poison)
Alias: `useOutgoingPoison`, `responsePoison`
Enregistre un nouveau poison pour infecter le trafic [sortant](#poisoning-phases).
#### toxy#rule(rule)
Alias: `useRule`
Enregistre une nouvelle règle.
#### toxy#withRule(rule)
Alias: `ifRule`, `whenRule`, `poisonRule`, `poisonFilter`
Applique une nouvelle règle au dernier poison enregistré.
#### toxy#enable(poison)
Active un poison par son identifiant.
#### toxy#disable(poison)
Désactive un poison par son identifiant.
#### toxy#remove(poison)
Retour: `boolean`
Supprime un poison de trafic entrant par son identifiant ou référence d'objet.
#### toxy#removeOutgoing(poison)
Retour: `boolean`
Supprime un poison de trafic sortant par son identifiant ou référence d'objet.
#### toxy#isEnabled(poison)
Retour: `boolean`
Vérifie si un poison est activé par son identifiant.
#### toxy#disableAll()
Alias: `disablePoisons`
Désactive tous les poisons enregistrés.
#### toxy#getPoison(name)
Retour: `Directive|null`
Recherche et récupère un poison enregistré dans la pile par son identifiant.
#### toxy#getIncomingPoison(name)
Retour: `Directive|null`
Recherche et récupère un poison `incoming` enregistré dans la pile par son identifiant.
#### toxy#getOutgoingPoison(name)
Retour: `Directive|null`
Recherche et récupère un poison `outgoing` enregistré dans la pile par son identifiant.
#### toxy#getPoisons()
Retour: `array<Directive>`
Retourne un tableau des poisons enregistrés.
#### toxy#getIncomingPoisons()
Retour: `array<Directive>`
Retourne un tableau des poisons `incoming` enregistrés.
#### toxy#getOutgoingPoisons()
Retour: `array<Directive>`
Retourne un tableau des poisons `outgoing` enregistrés.
#### toxy#flush()
Alias: `flushPoisons`
Supprime tous les poisons enregistrés pour les flux de trafic entrant et sortant.
#### toxy#enableRule(rule)
Active une règle par son identifiant.
#### toxy#disableRule(rule)
Désactive une règle par son identifiant.
#### toxy#removeRule(rule)
Retour: `boolean`
Supprime une règle par son identifiant.
#### toxy#disableRules()
Désactive toutes les règles enregistrées.
#### toxy#isRuleEnabled(rule)
Retour: `boolean`
Vérifie si la règle donnée est activée par son identifiant.
#### toxy#getRule(rule)
Retour: `Directive|null`
Recherche et récupère une règle enregistrée dans la pile par son identifiant.
#### toxy#getRules()
Retour: `array<Directive>`
Retourne un tableau des règles enregistrées sous forme de `Directive`.
#### toxy#flushRules()
Supprime toutes les règles.
### toxy.addPoison(name, fn)
Étend les poisons intégrés.
### toxy.addRule(name, fn)
Étend les règles intégrées.
### toxy.poisons `=>` Object
Expose une carte des poisons intégrés.
### toxy.rules `=>` Object
Expose une carte des règles intégrées.
### toxy.VERSION `=>` String
Version sémantique actuelle de toxy.
### ToxyRoute
`ToxyRoute` expose la même interface que l'interface globale `Toxy`, en ajoutant simplement quelques [méthodes supplémentaires](https://github.com/h2non/rocky#routepath) au niveau de la route.
Les actions ultérieures que vous effectuez sur l'API `ToxyRoute` ne seront applicables qu'au niveau de la route (imbriqué). En d'autres termes : vous connaissez déjà l'API.
Cet exemple dissipera probablement les doutes éventuels :```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'))
Un wrapper pratique utilisé en interne pour les poisons et les règles.
Normalement, vous n'avez pas besoin de connaître cette interface, mais à des fins de hacking ou pour des actions de plus bas niveau, elle peut être utile.
Retour : boolean
Retour : boolean
Retour : boolean
Alias : filter
Retour : function(req, res, next)
L'API HTTP toxy suit les conventions JSON API, y compris le lien hypermédia basé sur les ressources.
Pour un cas d'utilisation avancé, voir l'exemple du serveur d'administration.```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)
Pour plus de détails sur l'API programmatique d'administration, voir [ci-dessous](#programmatic-api-1).
### Autorisation
L'API HTTP peut être protégée contre les clients non autorisés.
Les clients autorisés doivent définir le jeton de clé API via les en-têtes HTTP `API-Key` ou `Authorization`.
Pour l'activer, vous devez simplement passer les options suivantes au serveur d'administration `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)
Hiérarchie :
toxy gérées
Accepte : application/json
Exemple de charge utile :```js { "name": "method", "options": "GET" }
#### DELETE /servers/:id/rules
#### GET /servers/:id/rules/:id
#### DELETE /servers/:id/rules/:id
### Poisons
#### GET /servers/:id/poison
#### POST /servers/:id/poisons
Accepte : `application/json`
Exemple de payload :```js
{
"name": "latency",
"phase": "outgoing",
"options": { "jitter": 1000 }
}
Accepte : application/json
Exemple de payload :```js { "name": "method", "options": "GET" }
#### DELETE /servers/:id/poisons/:id/rules
#### GET /servers/:id/poisons/:id/rules/:id
#### DELETE /servers/:id/poisons/:id/rules/:id
### Routes
#### GET /servers/:id/routes
#### POST /servers/:id/routes
Accepte : `application/json`
Exemple de payload :```js
{
"path": "/foo", // Required
"method": "GET", // use ALL for all the methods
"forward": "http://my.server", // Optional custom forward server URL
}
Accepts: application/json
Exemple de payload :```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
### Poisons de route
#### GET /servers/:id/routes/:id/poisons
#### POST /servers/:id/routes/:id/poisons
Accepte : `application/json`
Exemple de payload :```js
{
"name": "latency",
"phase": "outgoing",
"options": { "jitter": 1000 }
}
Accepte : application/json
Exemple de payload :```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
### API programmatique
Le serveur d'administration HTTP intégré fournit également une interface simple ouverte à l'extensibilité et à des fins de piratage.
Par exemple, vous pouvez brancher des middlewares supplémentaires au serveur d'administration, ou enregistrer de nouvelles routes.
#### toxy.admin([ opts ])
Retourne : `Admin`
**Options prises en charge** :
- **apiKey** `string` - Clé API optionnelle pour protéger le serveur
- **port** `number` - Optionnel. Port TCP d'écoute
- **cors** `boolean` - Activer CORS pour l'accès depuis un navigateur web
- **middleware** `array<function>` - Brancher des middlewares supplémentaires
- **ssl** `object` - Serveur HTTPS Node.js [options TLS](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener).
##### Admin#listen([ port, host ])
Démarrer l'écoute sur le réseau.
##### Admin#manage(toxy)
Gérer une instance du serveur `toxy`.
##### Admin#find(toxy)
Trouver une instance toxy. Accepte l'ID du serveur toxy ou une instance toxy.
##### Admin#remove(toxy)
Arrêter de gérer une instance toxy.
##### Admin#use(...middleware)
Enregistrer un middleware.
##### Admin#param(...middleware)
Enregistrer un middleware de paramètre.
##### Admin#get(path, [ ...middleware ])
Enregistrer une route GET.
##### Admin#post(path, [ ...middleware ])
Enregistrer une route POST.
##### Admin#put(path, [ ...middleware ])
Enregistrer une route PUT.
##### Admin#delete(path, [ ...middleware ])
Enregistrer une route DELETE.
##### Admin#patch(path, [ ...middleware ])
Enregistrer une route PATCH.
##### Admin#all(path, [ ...middleware ])
Enregistrer une route acceptant toute méthode HTTP.
##### Admin#middleware(req, res, next)
Middleware à brancher avec connect/express.
##### Admin#close(cb)
Arrêter le serveur.
## Licence
MIT - Tomas Aparicio
[](https://sourcegraph.com/github.com/h2non/toxy)