Skip to content

Commit a77afeb

Browse files
committed
fix #2052 simplejson barfs on thrown exceptions
1 parent 2224bef commit a77afeb

File tree

4 files changed

+139
-17
lines changed

4 files changed

+139
-17
lines changed

src/Elasticsearch.Net/Exceptions/ElasticsearchClientException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public string DebugInformation
4242
var failureReason = FailureReason.GetStringValue();
4343
if (this.FailureReason == PipelineFailure.Unexpected && (this.AuditTrail.HasAny()))
4444
{
45-
failureReason = this.AuditTrail.Last().Event.GetStringValue();
45+
failureReason = "Unrecoverable/Unexpected " + this.AuditTrail.Last().Event.GetStringValue();
4646
}
4747

4848
sb.AppendLine($"# FailureReason: {failureReason} while attempting {Request.Method.GetStringValue()} {Request.Uri}");

src/Elasticsearch.Net/Serialization/ElasticsearchDefaultSerializer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public T Deserialize<T>(Stream stream)
3030
{
3131
if (stream == null)
3232
return default(T);
33-
33+
3434
using (var ms = new MemoryStream())
3535
using (stream)
3636
{
@@ -45,7 +45,7 @@ public T Deserialize<T>(Stream stream)
4545

4646
public void Serialize(object data, Stream writableStream, SerializationFormatting formatting = SerializationFormatting.Indented)
4747
{
48-
var serialized = SimpleJson.SerializeObject(data);
48+
var serialized = SimpleJson.SerializeObject(data, ElasticsearchDefaultSerializer.Strategy);
4949
if (formatting == SerializationFormatting.None)
5050
serialized = RemoveNewLinesAndTabs(serialized);
5151
using (var ms = new MemoryStream(serialized.Utf8Bytes()))
@@ -63,4 +63,4 @@ private static string RemoveNewLinesAndTabs(string input)
6363
.ToArray());
6464
}
6565
}
66-
}
66+
}

src/Elasticsearch.Net/Serialization/ElasticsearchNetJsonStrategy.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,83 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Reflection;
5+
using System.Runtime.Serialization;
36

47
namespace Elasticsearch.Net
58
{
69
internal class ElasticsearchNetJsonStrategy : PocoJsonSerializerStrategy
710
{
811
public static readonly ElasticsearchNetJsonStrategy Instance = new ElasticsearchNetJsonStrategy();
912

13+
14+
public override bool TrySerializeNonPrimitiveObject(object input, out object output)
15+
{
16+
if (input is Exception)
17+
{
18+
var e = input as Exception;
19+
var o = new JsonObject();
20+
21+
var si = new SerializationInfo(e.GetType(), new FormatterConverter());
22+
var sc = new StreamingContext();
23+
e.GetObjectData(si, sc);
24+
25+
var helpUrl = si.GetString("HelpURL");
26+
var stackTrace = si.GetString("StackTraceString");
27+
var remoteStackTrace = si.GetString("RemoteStackTraceString");
28+
var remoteStackIndex = si.GetInt32("RemoteStackIndex");
29+
var exceptionMethod = si.GetString("ExceptionMethod");
30+
var hresult = si.GetInt32("HResult");
31+
var source = si.GetString("Source");
32+
var className = si.GetString("ClassName");
33+
34+
//TODO Loop over ISerializable data
35+
36+
o.Add("ClassName", className);
37+
o.Add("Message", e.Message);
38+
o.Add("Source", source);
39+
o.Add("StackTraceString", stackTrace);
40+
o.Add("RemoteStackTraceString", remoteStackTrace);
41+
o.Add("RemoteStackIndex", remoteStackIndex);
42+
o.Add("HResult", hresult);
43+
o.Add("HelpURL", helpUrl);
44+
this.WriteStructuredExceptionMethod(o, exceptionMethod);
45+
46+
output = o;
47+
return true;
48+
49+
}
50+
return base.TrySerializeNonPrimitiveObject(input, out output);
51+
}
52+
53+
private void WriteStructuredExceptionMethod(JsonObject o, string exceptionMethodString)
54+
{
55+
if (string.IsNullOrWhiteSpace(exceptionMethodString)) return;
56+
57+
var args = exceptionMethodString.Split('\0', '\n');
58+
59+
if (args.Length != 5) return;
60+
61+
var memberType = Int32.Parse(args[0], CultureInfo.InvariantCulture);
62+
var name = args[1];
63+
var assemblyName = args[2];
64+
var className = args[3];
65+
var signature = args[4];
66+
var an = new AssemblyName(assemblyName);
67+
var exceptionMethod = new JsonObject();
68+
69+
exceptionMethod.Add("Name", name);
70+
exceptionMethod.Add("AssemblyName", an.Name);
71+
exceptionMethod.Add("AssemblyVersion", an.Version.ToString());
72+
exceptionMethod.Add("AssemblyCulture", an.CultureName);
73+
exceptionMethod.Add("ClassName", className);
74+
exceptionMethod.Add("Signature", signature);
75+
exceptionMethod.Add("MemberType", memberType);
76+
o.Add("ExceptionMethod", exceptionMethod);
77+
78+
}
79+
80+
1081
public override object DeserializeObject(object value, Type type)
1182
{
1283
if (type == typeof(DynamicResponse))
@@ -37,4 +108,4 @@ public override object DeserializeObject(object value, Type type)
37108
return base.DeserializeObject(value, type);
38109
}
39110
}
40-
}
111+
}

src/Tests/Reproduce/GithubIssue2052.cs

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Reflection;
5+
using System.Runtime.Serialization;
6+
using System.Text;
37
using Elasticsearch.Net;
48
using FluentAssertions;
59
using Tests.Framework;
@@ -9,30 +13,77 @@ namespace Tests.Reproduce
913
public class GithubIssue2052
1014
{
1115

12-
[U] public void BadSimpleJsonDeserialization()
16+
[U]
17+
public void BadSimpleJsonDeserialization()
1318
{
1419

1520
var ex = this.GimmeACaughtException();
1621

17-
var document = new Dictionary<string,object>{
18-
{ "message", "My message"},
19-
{ "exception", ex }
22+
var document = new Dictionary<string, object>{
23+
{ "message", "My message"},
24+
{ "exception", ex }
2025
};
2126

2227
var pool = new StaticConnectionPool(new List<Uri> { new Uri("http://localhost:9200") });
2328
var memoryConnection = new InMemoryConnection();
24-
var connectionSettings = new ConnectionConfiguration(pool, memoryConnection);
29+
var connectionSettings = new ConnectionConfiguration(pool, memoryConnection)
30+
.DisableDirectStreaming();
2531
var client = new ElasticLowLevelClient(connectionSettings);
2632

27-
List<object> payload = new List<object>{
28-
new { index = new { _index = "myIndex", _type = "myDocumentType" } },
29-
document
33+
34+
var header = new { index = new { _index = "myIndex", _type = "myDocumentType" } };
35+
var payload = new List<object>{
36+
header,
37+
document
38+
};
39+
var response = client.Bulk<byte[]>(payload);
40+
41+
42+
var request = Encoding.UTF8.GetString(response.RequestBodyInBytes);
43+
var a = new AssemblyName(this.GetType().Assembly.FullName);
44+
45+
var si = new SerializationInfo(ex.GetType(), new FormatterConverter());
46+
var sc = new StreamingContext();
47+
ex.GetObjectData(si, sc);
48+
PostData<object> postData = new List<object>
49+
{
50+
header,
51+
new
52+
{
53+
message = "My message",
54+
exception = new
55+
{
56+
ClassName = "System.Exception",
57+
Message = "Some exception",
58+
Source = "Tests",
59+
StackTraceString = ex.StackTrace,
60+
RemoteStackTraceString = si.GetString("RemoteStackTraceString"),
61+
RemoteStackIndex = 0,
62+
HResult = si.GetInt32("HResult"),
63+
HelpURL = si.GetString("HelpURL"),
64+
ExceptionMethod = new
65+
{
66+
Name = nameof(GimmeACaughtException),
67+
AssemblyName = a.Name,
68+
AssemblyVersion = a.Version.ToString(),
69+
AssemblyCulture = a.CultureName,
70+
ClassName = this.GetType().FullName,
71+
Signature = $"System.Exception {nameof(GimmeACaughtException)}()",
72+
MemberType = 8
73+
}
74+
},
75+
}
3076
};
31-
Action act = () => client.Bulk<byte[]>(payload);
32-
var e = act.ShouldThrow<UnexpectedElasticsearchClientException>();
3377

34-
//throw new Exception(e.Subject.First().DebugInformation);
3578

79+
80+
81+
using (var ms = new MemoryStream())
82+
{
83+
postData.Write(ms, client.Settings);
84+
var expectedString = Encoding.UTF8.GetString(ms.ToArray());
85+
request.Should().Be(expectedString);
86+
}
3687
}
3788

3889
private Exception GimmeACaughtException()
@@ -41,7 +92,7 @@ private Exception GimmeACaughtException()
4192
{
4293
throw new Exception("Some exception");
4394
}
44-
catch(Exception e)
95+
catch (Exception e)
4596
{
4697
return e;
4798
}

0 commit comments

Comments
 (0)