diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e79e35..f49f1f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features 1. [#101](https://github.com/InfluxCommunity/influxdb3-csharp/pull/101): Add standard `user-agent` header to all calls. +1. [#110](https://github.com/InfluxCommunity/influxdb3-csharp/pull/110): InfluxDB Edge (OSS) error handling. ## 0.6.0 [2024-04-16] diff --git a/Client.Test/Internal/RestClientTest.cs b/Client.Test/Internal/RestClientTest.cs index 9859a75..c1e35ac 100644 --- a/Client.Test/Internal/RestClientTest.cs +++ b/Client.Test/Internal/RestClientTest.cs @@ -141,7 +141,7 @@ public void ErrorBody() } [Test] - public void ErrorJsonBody() + public void ErrorJsonBodyCloud() { CreateAndConfigureRestClient(new ClientConfig { @@ -168,6 +168,63 @@ public void ErrorJsonBody() }); } + [Test] + public void ErrorJsonBodyEdgeWithData() + { + CreateAndConfigureRestClient(new ClientConfig + { + Host = MockServerUrl, + }); + + MockServer + .Given(Request.Create().WithPath("/api").UsingPost()) + .RespondWith(Response.Create() + .WithHeader("X-Influx-Error", "not used") + .WithBody("{\"error\":\"parsing failed\", \"data\":{\"error_message\":\"invalid field value in line protocol for field 'value' on line 0\"}}") + .WithStatusCode(401)); + + var ae = Assert.ThrowsAsync(async () => + { + await _client.Request("api", HttpMethod.Post); + }); + + Assert.Multiple(() => + { + Assert.That(ae, Is.Not.Null); + Assert.That(ae.HttpResponseMessage, Is.Not.Null); + Assert.That(ae.Message, Is.EqualTo("invalid field value in line protocol for field 'value' on line 0")); + }); + } + + [Test] + public void ErrorJsonBodyEdgeWithoutData() + { + CreateAndConfigureRestClient(new ClientConfig + { + Host = MockServerUrl, + }); + + MockServer + .Given(Request.Create().WithPath("/api").UsingPost()) + .RespondWith(Response.Create() + .WithHeader("X-Influx-Error", "not used") + .WithBody("{\"error\":\"token does not have sufficient permissions\"}") + .WithStatusCode(401)); + + var ae = Assert.ThrowsAsync(async () => + { + await _client.Request("api", HttpMethod.Post); + }); + + Assert.Multiple(() => + { + Assert.That(ae, Is.Not.Null); + Assert.That(ae.HttpResponseMessage, Is.Not.Null); + Assert.That(ae.Message, Is.EqualTo("token does not have sufficient permissions")); + }); + } + + [Test] public void ErrorReason() { diff --git a/Client/Internal/RestClient.cs b/Client/Internal/RestClient.cs index 328c2c9..f1b7a41 100644 --- a/Client/Internal/RestClient.cs +++ b/Client/Internal/RestClient.cs @@ -93,7 +93,18 @@ internal async Task Request(string path, HttpMethod method, HttpContent? content if (new DataContractJsonSerializer(typeof(ErrorBody)).ReadObject(memoryStream) is ErrorBody errorBody) { - message = errorBody.Message; + if (!string.IsNullOrEmpty(errorBody.Message)) // Cloud + { + message = errorBody.Message; + } + else if ((errorBody.Data is not null) && !string.IsNullOrEmpty(errorBody.Data.ErrorMessage)) // Edge + { + message = errorBody.Data.ErrorMessage; + } + else if (!string.IsNullOrEmpty(errorBody.Error)) // Edge + { + message = errorBody.Error; + } } } catch (SerializationException se) @@ -131,5 +142,19 @@ internal async Task Request(string path, HttpMethod method, HttpContent? content [DataContract] internal class ErrorBody { - [DataMember(Name = "message")] public string? Message { get; set; } + [DataMember(Name = "message")] + public string? Message { get; set; } + + [DataMember(Name = "error")] + public string? Error { get; set; } + + [DataMember(Name = "data")] + public ErrorData? Data { get; set; } + + [DataContract] + internal class ErrorData + { + [DataMember(Name = "error_message")] + public string? ErrorMessage { get; set; } + } } \ No newline at end of file