Skip to content

Commit 0dc82a3

Browse files
committed
Support for parsing OP error responses
1 parent d6a8553 commit 0dc82a3

File tree

5 files changed

+334
-2
lines changed

5 files changed

+334
-2
lines changed

FirebaseAdmin/FirebaseAdmin.Tests/FirebaseExceptionTest.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414

1515
using System;
1616
using System.Collections.Generic;
17+
using System.Net;
1718
using System.Net.Http;
1819
using System.Net.Sockets;
20+
using System.Text;
1921
using Xunit;
2022

2123
namespace FirebaseAdmin.Tests
@@ -30,6 +32,7 @@ public void ErrorCodeAndMessage()
3032
Assert.Equal(ErrorCode.Internal, exception.ErrorCode);
3133
Assert.Equal("Test error message", exception.Message);
3234
Assert.Null(exception.InnerException);
35+
Assert.Null(exception.HttpResponse);
3336
}
3437

3538
[Fact]
@@ -41,6 +44,20 @@ public void InnerException()
4144
Assert.Equal(ErrorCode.Internal, exception.ErrorCode);
4245
Assert.Equal("Test error message", exception.Message);
4346
Assert.Same(inner, exception.InnerException);
47+
Assert.Null(exception.HttpResponse);
48+
}
49+
50+
[Fact]
51+
public void HttpResponse()
52+
{
53+
var inner = new Exception("Inner exception");
54+
var resp = new HttpResponseMessage();
55+
var exception = new FirebaseException(ErrorCode.Internal, "Test error message", inner, resp);
56+
57+
Assert.Equal(ErrorCode.Internal, exception.ErrorCode);
58+
Assert.Equal("Test error message", exception.Message);
59+
Assert.Same(inner, exception.InnerException);
60+
Assert.Same(resp, exception.HttpResponse);
4461
}
4562

4663
[Fact]
@@ -54,6 +71,7 @@ public void TimeOutError()
5471
Assert.Equal(
5572
"Timed out while making an API call: Test error message", exception.Message);
5673
Assert.Same(httpError, exception.InnerException);
74+
Assert.Null(exception.HttpResponse);
5775
}
5876

5977
[Fact]
@@ -78,6 +96,7 @@ public void NetworkUnavailableError()
7896
Assert.Equal(
7997
"Failed to establish a connection: Test error message", exception.Message);
8098
Assert.Same(httpError, exception.InnerException);
99+
Assert.Null(exception.HttpResponse);
81100
}
82101
}
83102

@@ -92,6 +111,100 @@ public void UnknownLowLevelError()
92111
"Unknown error while making a remote service call: Test error message",
93112
exception.Message);
94113
Assert.Same(httpError, exception.InnerException);
114+
Assert.Null(exception.HttpResponse);
115+
}
116+
117+
[Fact]
118+
public void PlatformError()
119+
{
120+
var json = @"{
121+
""error"": {
122+
""status"": ""UNAVAILABLE"",
123+
""message"": ""Test error message""
124+
}
125+
}";
126+
var resp = new HttpResponseMessage()
127+
{
128+
StatusCode = HttpStatusCode.ServiceUnavailable,
129+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
130+
};
131+
132+
var handler = new PlatformErrorHandler();
133+
var error = Assert.Throws<FirebaseException>(() => handler.ThrowIfError(resp, json));
134+
135+
Assert.Equal(ErrorCode.Unavailable, error.ErrorCode);
136+
Assert.Equal("Test error message", error.Message);
137+
Assert.Same(resp, error.HttpResponse);
138+
Assert.Null(error.InnerException);
139+
}
140+
141+
[Fact]
142+
public void PlatformErrorWithoutCode()
143+
{
144+
var json = @"{
145+
""error"": {
146+
""message"": ""Test error message""
147+
}
148+
}";
149+
var resp = new HttpResponseMessage()
150+
{
151+
StatusCode = HttpStatusCode.ServiceUnavailable,
152+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
153+
};
154+
155+
var handler = new PlatformErrorHandler();
156+
var error = Assert.Throws<FirebaseException>(() => handler.ThrowIfError(resp, json));
157+
158+
Assert.Equal(ErrorCode.Unavailable, error.ErrorCode);
159+
Assert.Equal("Test error message", error.Message);
160+
Assert.Same(resp, error.HttpResponse);
161+
Assert.Null(error.InnerException);
162+
}
163+
164+
[Fact]
165+
public void PlatformErrorWithoutMessage()
166+
{
167+
var json = @"{
168+
""error"": {
169+
""status"": ""INVALID_ARGUMENT"",
170+
}
171+
}";
172+
var resp = new HttpResponseMessage()
173+
{
174+
StatusCode = HttpStatusCode.ServiceUnavailable,
175+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
176+
};
177+
178+
var handler = new PlatformErrorHandler();
179+
var error = Assert.Throws<FirebaseException>(() => handler.ThrowIfError(resp, json));
180+
181+
Assert.Equal(ErrorCode.InvalidArgument, error.ErrorCode);
182+
Assert.Equal(
183+
$"Unexpected HTTP response with status: 503 (ServiceUnavailable)\n{json}",
184+
error.Message);
185+
Assert.Same(resp, error.HttpResponse);
186+
Assert.Null(error.InnerException);
187+
}
188+
189+
[Fact]
190+
public void PlatformErrorWithoutCodeOrMessage()
191+
{
192+
var json = @"{}";
193+
var resp = new HttpResponseMessage()
194+
{
195+
StatusCode = HttpStatusCode.ServiceUnavailable,
196+
Content = new StringContent(json, Encoding.UTF8, "application/json"),
197+
};
198+
199+
var handler = new PlatformErrorHandler();
200+
var error = Assert.Throws<FirebaseException>(() => handler.ThrowIfError(resp, json));
201+
202+
Assert.Equal(ErrorCode.Unavailable, error.ErrorCode);
203+
Assert.Equal(
204+
"Unexpected HTTP response with status: 503 (ServiceUnavailable)\n{}",
205+
error.Message);
206+
Assert.Same(resp, error.HttpResponse);
207+
Assert.Null(error.InnerException);
95208
}
96209
}
97210
}

FirebaseAdmin/FirebaseAdmin/FirebaseException.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,37 @@
1313
// limitations under the License.
1414

1515
using System;
16+
using System.Net.Http;
1617

1718
namespace FirebaseAdmin
1819
{
1920
/// <summary>
2021
/// Common error type for all exceptions raised by Firebase APIs.
2122
/// </summary>
22-
public sealed class FirebaseException : Exception
23+
public class FirebaseException : Exception
2324
{
2425
internal FirebaseException(string message)
2526
: base(message) { } // TODO: Remove this constructor
2627

2728
internal FirebaseException(string message, Exception inner)
2829
: base(message, inner) { } // TODO: Remove this constructor
2930

30-
internal FirebaseException(ErrorCode code, string message, Exception inner = null)
31+
internal FirebaseException(
32+
ErrorCode code,
33+
string message,
34+
Exception inner = null,
35+
HttpResponseMessage response = null)
3136
: base(message, inner)
3237
{
3338
this.ErrorCode = code;
39+
this.HttpResponse = response;
3440
}
3541

3642
/// <summary>
3743
/// Gets the platform-wide error code associated with this exception.
3844
/// </summary>
3945
internal ErrorCode ErrorCode { get; private set; } // TODO: Expose this as public
46+
47+
internal HttpResponseMessage HttpResponse { get; private set; }
4048
}
4149
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2019, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
17+
namespace FirebaseAdmin.Messaging
18+
{
19+
/// <summary>
20+
/// Exception type raised by Firebase Cloud Messaging APIs.
21+
/// </summary>
22+
public sealed class FirebaseMessagingException : FirebaseException
23+
{
24+
internal FirebaseMessagingException(
25+
ErrorCode code,
26+
string message,
27+
MessagingErrorCode? fcmCode = null,
28+
Exception inner = null)
29+
: base(code, message, inner)
30+
{
31+
this.MessagingErrorCode = fcmCode;
32+
}
33+
34+
/// <summary>
35+
/// Gets the Cloud Messaging error code associated with this exception. May be null.
36+
/// </summary>
37+
public MessagingErrorCode? MessagingErrorCode { get; private set; }
38+
}
39+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2019, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
namespace FirebaseAdmin.Messaging
16+
{
17+
/// <summary>
18+
/// Error codes that can be raised by the Cloud Messaging APIs.
19+
/// </summary>
20+
public enum MessagingErrorCode
21+
{
22+
/// <summary>
23+
/// APNs certificate or web push auth key was invalid or missing.
24+
/// </summary>
25+
ThirdPartyAuthError,
26+
27+
/// <summary>
28+
/// One or more argument specified in the request was invalid.
29+
/// </summary>
30+
InvalidArgument,
31+
32+
/// <summary>
33+
/// Internal server error.
34+
/// </summary>
35+
Internal,
36+
37+
/// <summary>
38+
/// Sending limit exceeded for the message target.
39+
/// </summary>
40+
QuotaExceeded,
41+
42+
/// <summary>
43+
/// The authenticated sender ID is different from the sender ID for the registration token.
44+
/// </summary>
45+
SenderIdMismatch,
46+
47+
/// <summary>
48+
/// Cloud Messaging service is temporarily unavailable.
49+
/// </summary>
50+
Unavailable,
51+
52+
/// <summary>
53+
/// App instance was unregistered from FCM. This usually means that the token used is no
54+
/// longer valid and a new one must be used.
55+
/// </summary>
56+
Unregistered,
57+
}
58+
}

0 commit comments

Comments
 (0)