Skip to content

Commit 7649fdd

Browse files
author
mwatson
committed
Change to allow controlling data collected for exceptions. Like post data, headers, cookies, etc
1 parent fe9b3c3 commit 7649fdd

File tree

10 files changed

+150
-94
lines changed

10 files changed

+150
-94
lines changed
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
-512 Bytes
Binary file not shown.
-1 KB
Binary file not shown.
-512 Bytes
Binary file not shown.

Dlls/StackifyLib/StackifyLib.dll

4.5 KB
Binary file not shown.

Src/StackifyLib/Config.cs

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,104 @@
33
using System.Linq;
44
using System.Text;
55
using System.Configuration;
6+
using System.Diagnostics;
7+
using Newtonsoft.Json;
68

79
namespace StackifyLib
810
{
911
/// <summary>
1012
/// Encapsulate settings retrieval mechanism. Currently supports config file and environment variables.
1113
/// Could be expanded to include other type of configuration servers later.
1214
/// </summary>
13-
sealed class Config
15+
public class Config
1416
{
15-
/// <summary>
16-
/// Attempts to fetch a setting value given the key.
17-
/// .NET configuration file will be used first, if the key is not found, environment variable will be used next.
18-
/// </summary>
19-
/// <param name="key">configuration key in config file or environment variable name.</param>
20-
/// <param name="defaultValue">If nothing is found, return optional defaultValue provided.</param>
21-
/// <returns>string value for the requested setting key.</returns>
22-
public static string Get(string key, string defaultValue = null)
17+
public static void LoadSettings()
18+
{
19+
try
20+
{
21+
CaptureErrorPostdata = Get("Stackify.CaptureErrorPostdata")
22+
.Equals("true", StringComparison.CurrentCultureIgnoreCase);
23+
24+
CaptureServerVariables = Get("Stackify.CaptureServerVariables")
25+
.Equals("true", StringComparison.CurrentCultureIgnoreCase);
26+
CaptureSessionVariables = Get("Stackify.CaptureSessionVariables")
27+
.Equals("true", StringComparison.CurrentCultureIgnoreCase);
28+
29+
CaptureErrorHeaders = Get("Stackify.CaptureErrorHeaders")
30+
.Equals("true", StringComparison.CurrentCultureIgnoreCase);
31+
32+
CaptureErrorCookies = Get("Stackify.CaptureErrorCookies")
33+
.Equals("true", StringComparison.CurrentCultureIgnoreCase);
34+
35+
CaptureErrorHeadersWhitelist = Get("Stackify.CaptureErrorHeadersWhitelist");
36+
37+
if (!string.IsNullOrEmpty(CaptureErrorHeadersWhitelist))
38+
{
39+
ErrorHeaderGoodKeys = CaptureErrorHeadersWhitelist.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
40+
}
41+
42+
CaptureErrorHeadersBlacklist = Get("Stackify.CaptureErrorHeadersBlacklist");
43+
if (!string.IsNullOrEmpty(CaptureErrorHeadersBlacklist))
44+
{
45+
ErrorHeaderBadKeys = CaptureErrorHeadersBlacklist.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
46+
}
47+
48+
CaptureErrorCookiesWhitelist = Get("Stackify.CaptureErrorCookiesWhitelist");
49+
if (!string.IsNullOrEmpty(CaptureErrorCookiesWhitelist))
50+
{
51+
ErrorCookiesGoodKeys = CaptureErrorCookiesWhitelist.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
52+
}
53+
54+
CaptureErrorCookiesBlacklist = Get("Stackify.CaptureErrorCookiesBlacklist");
55+
if (!string.IsNullOrEmpty(CaptureErrorCookiesBlacklist))
56+
{
57+
ErrorCookiesBadKeys = CaptureErrorCookiesBlacklist.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
58+
}
59+
60+
CaptureErrorSessionWhitelist = Get("Stackify.CaptureErrorSessionWhitelist");
61+
if (!string.IsNullOrEmpty(CaptureErrorSessionWhitelist))
62+
{
63+
ErrorSessionGoodKeys = CaptureErrorSessionWhitelist.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
64+
}
65+
66+
}
67+
catch (Exception ex)
68+
{
69+
Debug.WriteLine(ex.ToString());
70+
}
71+
}
72+
73+
public static List<string> ErrorHeaderGoodKeys = new List<string>();
74+
public static List<string> ErrorHeaderBadKeys = new List<string>();
75+
public static List<string> ErrorCookiesGoodKeys = new List<string>();
76+
public static List<string> ErrorCookiesBadKeys = new List<string>();
77+
public static List<string> ErrorSessionGoodKeys = new List<string>();
78+
79+
public static bool CaptureSessionVariables { get; set; } = false;
80+
public static bool CaptureServerVariables { get; set; } = false;
81+
public static bool CaptureErrorPostdata { get; set; } = false;
82+
public static bool CaptureErrorHeaders { get; set; } = true;
83+
public static bool CaptureErrorCookies { get; set; } = false;
84+
85+
public static string CaptureErrorSessionWhitelist { get; set; } = null;
86+
87+
public static string CaptureErrorHeadersWhitelist { get; set; } = null;
88+
89+
public static string CaptureErrorHeadersBlacklist { get; set; } = "cookie,authorization";
90+
91+
public static string CaptureErrorCookiesWhitelist { get; set; } = null;
92+
93+
public static string CaptureErrorCookiesBlacklist { get; set; } = ".ASPXAUTH";
94+
95+
96+
/// <summary>
97+
/// Attempts to fetch a setting value given the key.
98+
/// .NET configuration file will be used first, if the key is not found, environment variable will be used next.
99+
/// </summary>
100+
/// <param name="key">configuration key in config file or environment variable name.</param>
101+
/// <param name="defaultValue">If nothing is found, return optional defaultValue provided.</param>
102+
/// <returns>string value for the requested setting key.</returns>
103+
internal static string Get(string key, string defaultValue = null)
23104
{
24105
string v = null;
25106
try
@@ -36,7 +117,7 @@ public static string Get(string key, string defaultValue = null)
36117
if (v == null)
37118
v = defaultValue;
38119
}
39-
return v;
120+
return v ?? "";
40121
}
41122
}
42123
}

Src/StackifyLib/Internal/Logs/LogClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class LogClient : ILogClient
2626

2727
public LogClient(string loggerName, string apikey = null, string apiurl = null)
2828
{
29-
29+
Config.LoadSettings();
3030
StackifyAPILogger.Log("Creating new LogClient " + loggerName);
3131

3232
_LoggerName = loggerName;

Src/StackifyLib/Models/LogMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public override string ToString()
2020
{
2121
if (json != null)
2222
{
23-
return message + " " + JsonConvert.SerializeObject(json);
23+
return message + " " + JsonConvert.SerializeObject(json, new JsonSerializerSettings{ReferenceLoopHandling = ReferenceLoopHandling.Serialize});
2424
}
2525
else
2626
{

Src/StackifyLib/Models/WebRequestDetail.cs

Lines changed: 57 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.Collections.Specialized;
66
using System.IO;
7+
using System.Linq;
78
using System.Web;
89
using System.Web.Routing;
910

@@ -132,86 +133,93 @@ private void Load(HttpContext context)
132133
{
133134
if (request.QueryString != null)
134135
{
135-
QueryString = ToKeyValues(request.QueryString, false);
136+
QueryString = ToKeyValues(request.QueryString, null, null);
136137
}
137138

138-
if (request.ServerVariables != null)
139+
if (request.ServerVariables != null && Config.CaptureServerVariables)
139140
{
140141
List<string> badKeys = new List<string>();
141142
badKeys.AddRange(new string[] { "all_http", "all_raw", "http_cookie" });
142143

143-
var serverVars = ToKeyValues(request.ServerVariables, false, badKeys);
144+
var serverVars = ToKeyValues(request.ServerVariables, null, badKeys);
144145
foreach (var serverVar in serverVars)
145146
{
146147
_Error.ServerVariables[serverVar.Key] = serverVar.Value;
147148
}
148149
}
149150

150-
if (request.Headers != null)
151+
if (request.Headers != null && Config.CaptureErrorHeaders)
151152
{
152-
List<string> badKeys = new List<string>();
153-
badKeys.AddRange(new string[] { "cookie" });
153+
if (Config.ErrorHeaderBadKeys == null)
154+
{
155+
Config.ErrorHeaderBadKeys = new List<string>();
156+
}
157+
158+
if (!Config.ErrorHeaderBadKeys.Contains("cookie"))
159+
{
160+
Config.ErrorHeaderBadKeys.Add("cookie");
161+
}
154162

155-
Headers = ToKeyValues(request.Headers, false, badKeys);
163+
Headers = ToKeyValues(request.Headers, Config.ErrorHeaderGoodKeys, Config.ErrorHeaderBadKeys);
156164
}
157165

158-
if (request.Cookies != null)
166+
if (request.Cookies != null && Config.CaptureErrorCookies)
159167
{
160-
Cookies = ToKeyValues(request.Cookies, true);
161-
162-
//if (Cookies != null)
163-
//{
164-
// foreach (var item in Cookies)
165-
// {
166-
// Cookies[item.Key] = "X-MASKED-X";
167-
// }
168-
//}
169-
170-
//if (Cookies.ContainsKey(".ASPXAUTH"))
171-
//{
172-
// Cookies[".ASPXAUTH"] = "X-MASKED-X";
173-
//}
168+
Cookies = ToKeyValues(request.Cookies, Config.ErrorCookiesGoodKeys, Config.ErrorCookiesBadKeys);
174169
}
175170

176-
if (request.Form != null)
171+
if (request.Form != null && Config.CaptureErrorPostdata)
177172
{
178-
PostData = ToKeyValues(request.Form, true);
179-
180-
//if (PostData != null)
181-
//{
182-
// foreach (var item in PostData)
183-
// {
184-
// PostData[item.Key] = "X-MASKED-X";
185-
// }
186-
//}
173+
PostData = ToKeyValues(request.Form,null, null);
187174
}
188175

189-
if (context.Session != null)
176+
if (context.Session != null && Config.CaptureSessionVariables && Config.ErrorSessionGoodKeys.Any())
190177
{
191-
SessionData = ToKeyValues(context.Session, true);
178+
SessionData = ToKeyValues(context.Session, Config.ErrorSessionGoodKeys, null);
192179
}
193180

194-
var contentType = context.Request.Headers["Content-Type"];
195-
196-
if (contentType != "text/html" && contentType != "application/x-www-form-urlencoded" && context.Request.RequestType != "GET")
181+
if (Config.CaptureErrorPostdata)
197182
{
198-
int length = 4096;
199-
string postBody = new StreamReader(context.Request.InputStream).ReadToEnd();
200-
if (postBody.Length < length)
183+
var contentType = context.Request.Headers["Content-Type"];
184+
185+
if (contentType != "text/html" && contentType != "application/x-www-form-urlencoded" &&
186+
context.Request.RequestType != "GET")
201187
{
202-
length = postBody.Length;
203-
}
188+
int length = 4096;
189+
string postBody = new StreamReader(context.Request.InputStream).ReadToEnd();
190+
if (postBody.Length < length)
191+
{
192+
length = postBody.Length;
193+
}
204194

205-
PostDataRaw = postBody.Substring(0, length);
195+
PostDataRaw = postBody.Substring(0, length);
196+
}
206197
}
207198
}
208199
catch (Exception)
209200
{
210201
}
211202
}
212203

204+
internal static void AddKey(string key, string value, Dictionary<string, string> dictionary, List<string> goodKeys, List<string> badKeys)
205+
{
206+
//is this key in the bad key list?
207+
if (badKeys != null && badKeys.Any(x => x.Equals(key, StringComparison.CurrentCultureIgnoreCase)))
208+
{
209+
dictionary[key] = "X-MASKED-X";
210+
return;
211+
}
212+
//if not in the good key list, return
213+
//if good key list is empty, we let it take it
214+
else if (goodKeys != null && goodKeys.Any() && !goodKeys.Any(x => x.Equals(key, StringComparison.CurrentCultureIgnoreCase)))
215+
{
216+
return;
217+
}
218+
219+
dictionary[key] = value;
220+
}
213221

214-
internal static Dictionary<string, string> ToKeyValues(HttpCookieCollection collection, bool keysOnly)
222+
internal static Dictionary<string, string> ToKeyValues(HttpCookieCollection collection, List<string> goodKeys, List<string> badKeys)
215223
{
216224
var keys = collection.AllKeys;
217225
var items = new Dictionary<string, string>();
@@ -224,17 +232,8 @@ internal static Dictionary<string, string> ToKeyValues(HttpCookieCollection coll
224232

225233
if (cookie != null && !string.IsNullOrWhiteSpace(cookie.Value) && !items.ContainsKey(key))
226234
{
227-
228-
if (keysOnly)
229-
{
230-
items.Add(key, "X-MASKED-X");
231-
}
232-
else
233-
{
234-
items.Add(key, cookie.Value);
235-
}
235+
AddKey(key, cookie.Value, items, goodKeys, badKeys);
236236
}
237-
238237
}
239238
catch (Exception)
240239
{
@@ -245,7 +244,7 @@ internal static Dictionary<string, string> ToKeyValues(HttpCookieCollection coll
245244
return items;
246245
}
247246

248-
internal static Dictionary<string, string> ToKeyValues(NameValueCollection collection, bool keysOnly, List<string> skipKeysList = null)
247+
internal static Dictionary<string, string> ToKeyValues(NameValueCollection collection, List<string> goodKeys, List<string> badKeys)
249248
{
250249
var keys = collection.AllKeys;
251250
var items = new Dictionary<string, string>();
@@ -254,25 +253,8 @@ internal static Dictionary<string, string> ToKeyValues(NameValueCollection colle
254253
{
255254
try
256255
{
257-
if (skipKeysList != null && skipKeysList.Contains(key.ToLower()))
258-
{
259-
continue;
260-
}
261-
262256
string val = collection[key];
263-
264-
if (!string.IsNullOrWhiteSpace(val))
265-
{
266-
if (keysOnly)
267-
{
268-
items.Add(key, "X-MASKED-X");
269-
}
270-
else
271-
{
272-
items.Add(key, val);
273-
}
274-
}
275-
257+
AddKey(key, val, items, goodKeys, badKeys);
276258
}
277259
catch (Exception)
278260
{
@@ -284,7 +266,7 @@ internal static Dictionary<string, string> ToKeyValues(NameValueCollection colle
284266
}
285267

286268

287-
internal static Dictionary<string, string> ToKeyValues(System.Web.SessionState.HttpSessionState collection, bool keysOnly)
269+
internal static Dictionary<string, string> ToKeyValues(System.Web.SessionState.HttpSessionState collection, List<string> goodKeys, List<string> badKeys)
288270
{
289271
var keys = collection.Keys;
290272
var items = new Dictionary<string, string>();
@@ -297,14 +279,7 @@ internal static Dictionary<string, string> ToKeyValues(System.Web.SessionState.H
297279

298280
if (val != null && !string.IsNullOrWhiteSpace(val.ToString()) && items.ContainsKey(key))
299281
{
300-
if (keysOnly)
301-
{
302-
items.Add(key, "X-MASKED-X");
303-
}
304-
else
305-
{
306-
items.Add(key, val.ToString());
307-
}
282+
AddKey(key, val.ToString(), items, goodKeys, badKeys);
308283
}
309284

310285
}

0 commit comments

Comments
 (0)