Skip to content

Commit 7fa876c

Browse files
committed
allow configuring of errors the proxy may produce
1 parent 6e4de62 commit 7fa876c

File tree

6 files changed

+52
-7
lines changed

6 files changed

+52
-7
lines changed

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ If you've defined a mock response to the specific request, the proxy will serve
5757
Depending on the configured fail ratio, the proxy will either pass the request through to Microsoft Graph or return one of the relevant network codes with a matching error response.
5858

5959
> **Important**
60-
>
60+
>
6161
> When closing the proxy, press the Enter key in the proxy's window, so that the proxy unregisters itself from your machine. If you terminate the proxy's process, you will lose network connection. To restore your connection in such case, start the proxy again, and close it by pressing Enter.
6262
6363
## Configuration
@@ -311,9 +311,18 @@ Setting|Description|Command-line option|Allowed values|Default value
311311
`port`|Port on which the proxy should listen to traffic|`-p, --port`|integer|`8000`
312312
`failureRate`|Rate of requests to Microsoft Graph between `0` and `100` that the proxy should fail. Set to `0` to pass all requests to Microsoft Graph, and to `100` to fail all requests.|`-f, --failure-rate`|`0..100`|`50`
313313
`noMocks`|Don't use mock responses|`--no-mocks`|`true`, `false`|`false`
314+
`allowedErrors`|List of http status code errors the proxy may produce when failing a request|`--allowed-errors -a`|`429 500 502 503 504 507`|`429 500 502 503 504 507`
314315
`cloud`|Which Microsoft Cloud to use for listening to requests|`-c, --cloud`|As defined in the `cloudHosts` setting|`global`
315316
`cloudHosts`|List of Microsoft Clouds allowed for testing||Key-value pairs of name and host name, eg. `"global": "graph.microsoft.com"`|See the `appsettings.json` file
316317

318+
#### Example usage:
319+
320+
```
321+
msgraph-chaos-proxy.exe --port 8080 --failure-rate 50 --no-mocks --allowed-errors 429 503
322+
```
323+
324+
Will configure the proxy listening on port 8080 to fail 50% of requests with an http status code of either 429 or 503 and ignore any mock responses that may have been provided in the `responses.json` file
325+
317326
## Frequently Asked Questions
318327

319328
### Does Graph Chaos Proxy upload any data to Microsoft?
@@ -322,4 +331,12 @@ No, it doesn't. While the proxy intercepts all network traffic on your machine,
322331

323332
### I've got no internet connection after using Graph Chaos Proxy
324333

325-
If you terminate the Graph Chaos Proxy process, the proxy won't be able to unregister itself and you won't have network connection on your machine. To restore network connection, start the proxy and close it by pressing Enter, which will gracefully close the proxy unregistering it on your machine and restoring the regular network connection.
334+
If you terminate the Graph Chaos Proxy process, the proxy won't be able to unregister itself and you won't have network connection on your machine. To restore network connection, start the proxy and close it by pressing Enter, which will gracefully close the proxy unregistering it on your machine and restoring the regular network connection.
335+
336+
### I keep getting 429 responses
337+
338+
If you have the failure rate at 100% then no request can ever succeed. If you configure a lower failure rate then a previously throttled request will be passed to Microsoft Graph provided the `Retry-After` time period has elapsed.
339+
340+
### I have a 429 response with no `Retry-After` header
341+
342+
As documented in the [Best practices to handle throttling](https://learn.microsoft.com/en-us/graph/throttling#best-practices-to-handle-throttling) an exponential backoff retry policy is recommended.

msgraph-chaos-proxy/ChaosEngine.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ public ChaosEngine(ChaosProxyConfiguration config) {
7979

8080
_random = new Random();
8181
_throttledRequests = new Dictionary<string, DateTime>();
82+
if (_config.AllowedErrors.Any()) {
83+
foreach(string k in _methodStatusCode.Keys) {
84+
_methodStatusCode[k] = _methodStatusCode[k].Where(e => _config.AllowedErrors.Any(a => (int)e == a)).ToArray();
85+
}
86+
}
8287
}
8388

8489
public async Task Run(CancellationToken? cancellationToken) {
@@ -222,7 +227,7 @@ private void FailResponse(SessionEventArgs e, ResponseComponents r, FailMode fai
222227
// there's no matching mock response so pick a random response
223228
// for the current request method
224229
var methodStatusCodes = _methodStatusCode[e.HttpClient.Request.Method];
225-
r.ErrorStatus = methodStatusCodes[_random.Next(0, methodStatusCodes.Length - 1)];
230+
r.ErrorStatus = methodStatusCodes[_random.Next(0, methodStatusCodes.Length)];
226231
}
227232
}
228233

msgraph-chaos-proxy/ChaosHost.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,31 @@ public RootCommand GetRootCommand() {
2222
rateOption.SetDefaultValue(50);
2323

2424
var noMocksOptions = new Option<bool>("--no-mocks", "Disable loading mock requests");
25+
noMocksOptions.AddAlias("-n");
2526
noMocksOptions.ArgumentHelpName = "no mocks";
27+
noMocksOptions.SetDefaultValue(false);
2628

2729
var cloudOption = new Option<string>("--cloud", "Set the target cloud to proxy requests for");
2830
cloudOption.AddAlias("-c");
2931
cloudOption.ArgumentHelpName = "cloud";
3032
cloudOption.SetDefaultValue("global");
33+
34+
var allowedErrorsOption = new Option<IEnumerable<int>>("--allowed-errors", "List of errors that the chaos proxy may produce");
35+
allowedErrorsOption.AddAlias("-a");
36+
allowedErrorsOption.ArgumentHelpName = "allowed errors";
37+
allowedErrorsOption.AllowMultipleArgumentsPerToken = true;
38+
allowedErrorsOption.SetDefaultValue(new List<int> { 429, 500, 502, 503, 504, 507 });
3139

3240
var command = new RootCommand
3341
{
3442
portOption,
3543
rateOption,
3644
noMocksOptions,
3745
cloudOption,
46+
allowedErrorsOption
3847
};
3948
command.Description = "HTTP proxy to create random failures for calls to Microsoft Graph";
40-
command.Handler = new ChaosProxyCommandHandler(portOption, rateOption, noMocksOptions, cloudOption);
49+
command.Handler = new ChaosProxyCommandHandler(portOption, rateOption, noMocksOptions, cloudOption, allowedErrorsOption);
4150

4251
return command;
4352
}

msgraph-chaos-proxy/ChaosProxyCommandHandler.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ public class ChaosProxyCommandHandler : ICommandHandler {
99
public Option<int> Rate { get; set; }
1010
public Option<bool> DisableMocks { get; set; }
1111
public Option<string> Cloud { get; set; }
12+
public Option<IEnumerable<int>> AllowedErrors { get; }
1213

13-
14-
public ChaosProxyCommandHandler(Option<int> port, Option<int> rate, Option<bool> disableMocks, Option<string> cloud)
15-
{
14+
public ChaosProxyCommandHandler(Option<int> port, Option<int> rate, Option<bool> disableMocks, Option<string> cloud, Option<IEnumerable<int>> allowedErrors) {
1615
Port = port ?? throw new ArgumentNullException(nameof(port));
1716
Rate = rate ?? throw new ArgumentNullException(nameof(rate));
1817
DisableMocks = disableMocks ?? throw new ArgumentNullException(nameof(disableMocks));
1918
Cloud = cloud ?? throw new ArgumentNullException(nameof(cloud));
19+
AllowedErrors = allowedErrors ?? throw new ArgumentNullException(nameof(allowedErrors));
2020
}
2121

2222

@@ -29,10 +29,12 @@ public async Task<int> InvokeAsync(InvocationContext context) {
2929
int failureRate = context.ParseResult.GetValueForOption(Rate);
3030
bool disableMocks = context.ParseResult.GetValueForOption(DisableMocks);
3131
string? cloud = context.ParseResult.GetValueForOption(Cloud);
32+
IEnumerable<int> allowedErrors = context.ParseResult.GetValueForOption(AllowedErrors) ?? Enumerable.Empty<int>();
3233
CancellationToken? cancellationToken = (CancellationToken?)context.BindingContext.GetService(typeof(CancellationToken?));
3334
Configuration.Port = port;
3435
Configuration.FailureRate = failureRate;
3536
Configuration.NoMocks = disableMocks;
37+
Configuration.AllowedErrors = allowedErrors;
3638
if (cloud is not null)
3739
Configuration.Cloud = cloud;
3840

msgraph-chaos-proxy/ChaosProxyConfiguration.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class ChaosProxyConfiguration : IDisposable
1414
public string Cloud { get; set; } = "global";
1515
[JsonPropertyName("cloudHosts")]
1616
public Dictionary<string, string> CloudHosts { get; set; } = new();
17+
[JsonPropertyName("allowedErrors")]
18+
public IEnumerable<int> AllowedErrors { get; set; } = Array.Empty<int>();
1719

1820
public string HostName => CloudHosts.ContainsKey(Cloud) ? CloudHosts[Cloud] : throw new ArgumentOutOfRangeException(nameof(Cloud), InvalidCloudMessage);
1921

msgraph-chaos-proxy/Properties/launchSettings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
"commandName": "Project",
1515
"commandLineArgs": "--port 8080 --failure-rate 100 --no-mocks --cloud china",
1616
"hotReloadEnabled": true
17+
},
18+
"High chaos only 429 503 and no mocks": {
19+
"commandName": "Project",
20+
"commandLineArgs": "--port 8080 --failure-rate 95 -a 429 503 --no-mocks",
21+
"hotReloadEnabled": true
22+
},
23+
"High chaos only 429 and no mocks": {
24+
"commandName": "Project",
25+
"commandLineArgs": "--port 8080 --failure-rate 95 -a 429 --no-mocks",
26+
"hotReloadEnabled": true
1727
}
1828
}
1929
}

0 commit comments

Comments
 (0)