Skip to content

Commit 9defd46

Browse files
Erik BylundMikkel Sørensen
authored andcommitted
Add error data if the error is not of a parseable json
1 parent a5e827a commit 9defd46

File tree

3 files changed

+111
-33
lines changed

3 files changed

+111
-33
lines changed

Runtime/Client/LootLockerServerApi.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,15 @@ IEnumerator coroutine()
132132
};
133133

134134
response.errorData = LootLockerJson.DeserializeObject<LootLockerErrorData>(webRequest.downloadHandler.text);
135-
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)(response.errorData.message +
136-
(!string.IsNullOrEmpty(response.errorData.doc_url) ? " -- " + response.errorData.doc_url : ""));
137-
OnServerResponse?.Invoke(response);
138135

136+
// Error data was not parseable, populate with what we know
137+
if (response.errorData == null)
138+
{
139+
response.errorData = new LootLockerErrorData((int)webRequest.responseCode, webRequest.downloadHandler.text);
140+
}
141+
142+
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)(response.errorData.ToString());
143+
OnServerResponse?.Invoke(response);
139144
}
140145
}
141146
}
@@ -237,7 +242,7 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
237242
return;
238243
}
239244
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired, please refresh it");
240-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
245+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
241246
return;
242247
}
243248
case Platforms.AppleSignIn:
@@ -251,7 +256,7 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
251256
return;
252257
}
253258
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired, please refresh it");
254-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
259+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
255260
return;
256261
}
257262
case Platforms.Epic:
@@ -265,7 +270,7 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
265270
return;
266271
}
267272
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired, please refresh it");
268-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
273+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
269274
return;
270275
}
271276
case Platforms.Google:
@@ -279,7 +284,7 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
279284
return;
280285
}
281286
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired, please refresh it");
282-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
287+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
283288
return;
284289
}
285290
case Platforms.Remote:
@@ -293,14 +298,14 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
293298
return;
294299
}
295300
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired, please refresh it");
296-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
301+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
297302
return;
298303
}
299304
case Platforms.NintendoSwitch:
300305
case Platforms.Steam:
301306
{
302307
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Warning)($"Token has expired and token refresh is not supported for {CurrentPlatform.GetFriendlyString()}");
303-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
308+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
304309
return;
305310
}
306311
case Platforms.PlayStationNetwork:
@@ -317,8 +322,8 @@ private void RefreshTokenAndCompleteCall(LootLockerServerRequest cachedRequest,
317322
case Platforms.None:
318323
default:
319324
{
320-
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)($"Platform {CurrentPlatform.GetFriendlyString()} not supported");
321-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>($"Platform {CurrentPlatform.GetFriendlyString()} not supported", 401));
325+
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)($"Token refresh for platform {CurrentPlatform.GetFriendlyString()} not supported");
326+
onComplete?.Invoke(LootLockerResponseFactory.NetworkError<LootLockerResponse>($"Token refresh for platform {CurrentPlatform.GetFriendlyString()} not supported", 401));
322327
return;
323328
}
324329
}
@@ -335,14 +340,14 @@ private void CompleteCall(LootLockerServerRequest cachedRequest, LootLockerSessi
335340
if (!sessionRefreshResponse.success)
336341
{
337342
LootLockerLogger.GetForLogLevel()("Session refresh failed");
338-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
343+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
339344
return;
340345
}
341346

342347
if (cachedRequest.retryCount >= 4)
343348
{
344349
LootLockerLogger.GetForLogLevel()("Session refresh failed");
345-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("Token Expired", 401));
350+
onComplete?.Invoke(LootLockerResponseFactory.TokenExpiredError<LootLockerResponse>());
346351
return;
347352
}
348353

Runtime/Client/LootLockerServerRequest.cs

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ public enum LootLockerHTTPMethod
9292

9393
public class LootLockerErrorData
9494
{
95+
public LootLockerErrorData(int httpStatusCode, string errorMessage)
96+
{
97+
code = $"HTTP{httpStatusCode}";
98+
doc_url = $"https://developer.mozilla.org/docs/Web/HTTP/Status/{httpStatusCode}";
99+
message = errorMessage;
100+
}
101+
102+
public LootLockerErrorData() { }
103+
95104
/// <summary>
96105
/// A descriptive code identifying the error.
97106
/// </summary>
@@ -123,7 +132,49 @@ public class LootLockerErrorData
123132
/// <returns>string used to debug errors</returns>
124133
public override string ToString()
125134
{
126-
return $"We encountered an unexpected server error. Please try again later.\n If the issue persists, please contact LootLocker support and reference the following error details:\n trace ID - {trace_id},\n request ID - {request_id},\n message - {message}.";
135+
// Empty error, make sure we print something
136+
if (string.IsNullOrEmpty(message) && string.IsNullOrEmpty(trace_id) && string.IsNullOrEmpty(request_id))
137+
{
138+
return $"An unexpected LootLocker error without error data occurred. Please try again later.\n If the issue persists, please contact LootLocker support.";
139+
}
140+
141+
//Print the most important info first
142+
string prettyError = $"LootLocker Error: \"{message}\"";
143+
144+
// Look for intermittent, non user errors
145+
if (code.StartsWith("HTTP5"))
146+
{
147+
prettyError +=
148+
$"\nTry again later. If the issue persists, please contact LootLocker support and provide the following error details:\n trace ID - \"{trace_id}\",\n request ID - \"{request_id}\",\n message - \"{message}\".";
149+
if (!string.IsNullOrEmpty(doc_url))
150+
{
151+
prettyError += $"\nFor more information, see {doc_url} (error code was \"{code}\").";
152+
}
153+
}
154+
// Print user errors
155+
else
156+
{
157+
prettyError +=
158+
$"\nThere was a problem with your request. The error message provides information on the problem and will help you fix it.";
159+
if (!string.IsNullOrEmpty(doc_url))
160+
{
161+
prettyError += $"\nFor more information, see {doc_url} (error code was \"{code}\").";
162+
}
163+
164+
prettyError +=
165+
$"\nIf you are unable to fix the issue, contact LootLocker support and provide the following error details:";
166+
if (!string.IsNullOrEmpty(trace_id))
167+
{
168+
prettyError += $"\n trace ID - \"{trace_id}\"";
169+
}
170+
if (!string.IsNullOrEmpty(request_id))
171+
{
172+
prettyError += $"\n request ID - \"{request_id}\"";
173+
}
174+
175+
prettyError += $"\n message - \"{message}\".";
176+
}
177+
return prettyError;
127178
}
128179
}
129180

@@ -181,14 +232,11 @@ public static T Deserialize<T>(LootLockerResponse serverResponse,
181232
{
182233
if (serverResponse == null)
183234
{
184-
return LootLockerResponseFactory.Error<T>("Unknown error, please check your internet connection.");
235+
return LootLockerResponseFactory.ClientError<T>("Unknown error, please check your internet connection.");
185236
}
186237
else if (serverResponse.errorData != null)
187238
{
188-
if(!string.IsNullOrEmpty(serverResponse.errorData.code)) {
189-
return new T() { success = false, errorData = serverResponse.errorData, statusCode = serverResponse.statusCode };
190-
}
191-
return new T() { success = false, errorData = serverResponse.errorData, statusCode = serverResponse.statusCode };
239+
return new T() { success = false, errorData = serverResponse.errorData, statusCode = serverResponse.statusCode, text = serverResponse.text };
192240
}
193241

194242
var response = LootLockerJson.DeserializeObject<T>(serverResponse.text, options ?? LootLockerJsonSettings.Default) ?? new T();
@@ -224,41 +272,66 @@ public class LootLockerPaginationResponse<TKey>
224272
public class LootLockerResponseFactory
225273
{
226274
/// <summary>
227-
/// Construct an error response to send to the client.
275+
/// Construct an error response from a network request to send to the client.
276+
/// </summary>
277+
public static T NetworkError<T>(string errorMessage, int httpStatusCode) where T : LootLockerResponse, new()
278+
{
279+
return new T()
280+
{
281+
success = false,
282+
text = "{ \"message\": \"" + errorMessage + "\"}",
283+
statusCode = httpStatusCode,
284+
errorData = new LootLockerErrorData(httpStatusCode, errorMessage)
285+
};
286+
}
287+
288+
/// <summary>
289+
/// Construct an error response from a client side error to send to the client.
228290
/// </summary>
229-
public static T Error<T>(string errorMessage, int statusCode = 0) where T : LootLockerResponse, new()
291+
public static T ClientError<T>(string errorMessage) where T : LootLockerResponse, new()
230292
{
231293
return new T()
232294
{
233295
success = false,
234296
text = "{ \"message\": \"" + errorMessage + "\"}",
235-
statusCode = statusCode,
236-
errorData = new LootLockerErrorData() { message = errorMessage }
297+
statusCode = 0,
298+
errorData = new LootLockerErrorData
299+
{
300+
message = errorMessage,
301+
}
237302
};
238303
}
239304

305+
/// <summary>
306+
/// Construct an error response for token expiration.
307+
/// </summary>
308+
public static T TokenExpiredError<T>() where T : LootLockerResponse, new()
309+
{
310+
return NetworkError<T>("Token Expired", 401);
311+
}
312+
240313
/// <summary>
241314
/// Construct an error response specifically when the SDK has not been initialized.
242315
/// </summary>
243316
public static T SDKNotInitializedError<T>() where T : LootLockerResponse, new()
244317
{
245-
return Error<T>("The LootLocker SDK has not been initialized, please start a session to call this method");
318+
return ClientError<T>("The LootLocker SDK has not been initialized, please start a session to call this method");
246319
}
247320

248321
/// <summary>
249322
/// Construct an error response because an unserializable input has been given
250323
/// </summary>
251324
public static T InputUnserializableError<T>() where T : LootLockerResponse, new()
252325
{
253-
return Error<T>("Method parameter could not be serialized");
326+
return ClientError<T>("Method parameter could not be serialized");
254327
}
255328

256329
/// <summary>
257330
/// Construct an error response because the rate limit has been hit
258331
/// </summary>
259332
public static T RateLimitExceeded<T>(string method, int secondsLeftOfRateLimit) where T : LootLockerResponse, new()
260333
{
261-
return Error<T>($"Your request to {method} was not sent. You are sending too many requests and are being rate limited for {secondsLeftOfRateLimit} seconds");
334+
return ClientError<T>($"Your request to {method} was not sent. You are sending too many requests and are being rate limited for {secondsLeftOfRateLimit} seconds");
262335
}
263336
}
264337

@@ -498,7 +571,7 @@ public static void CallDomainAuthAPI(string endPoint, LootLockerHTTPMethod httpM
498571
#if UNITY_EDITOR
499572
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)("LootLocker domain key must be set in settings");
500573
#endif
501-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("LootLocker domain key must be set in settings"));
574+
onComplete?.Invoke(LootLockerResponseFactory.ClientError<LootLockerResponse>("LootLocker domain key must be set in settings"));
502575

503576
return;
504577
}
@@ -527,7 +600,7 @@ public static void UploadFile(string endPoint, LootLockerHTTPMethod httpMethod,
527600
#if UNITY_EDITOR
528601
LootLockerLogger.GetForLogLevel(LootLockerLogger.LogLevel.Error)("File content is empty, not allowed.");
529602
#endif
530-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerResponse>("File content is empty, not allowed."));
603+
onComplete?.Invoke(LootLockerResponseFactory.ClientError<LootLockerResponse>("File content is empty, not allowed."));
531604
return;
532605
}
533606
if (useAuthToken)

Runtime/Game/LootLockerSDKManager.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ public static void StartGuestSession(string identifier, Action<LootLockerGuestSe
301301

302302
if (identifier.Length == 0)
303303
{
304-
onComplete?.Invoke(LootLockerResponseFactory.Error<LootLockerGuestSessionResponse>("identifier cannot be empty"));
304+
onComplete?.Invoke(LootLockerResponseFactory.ClientError<LootLockerGuestSessionResponse>("Identifier cannot be empty when calling StartGuestSession (if you want an identifier to be generated for you, please use StartGuestSession(Action<LootLockerGuestSessionResponse> onComplete)"));
305305
return;
306306
}
307307
CurrentPlatform.Set(Platforms.Guest);
@@ -1187,14 +1187,14 @@ public static void StartWhiteLabelSession(Action<LootLockerSessionResponse> onCo
11871187
string existingSessionToken = PlayerPrefs.GetString("LootLockerWhiteLabelSessionToken", "");
11881188
if (string.IsNullOrEmpty(existingSessionToken))
11891189
{
1190-
onComplete(LootLockerResponseFactory.Error<LootLockerSessionResponse>("no session token found"));
1190+
onComplete(LootLockerResponseFactory.ClientError<LootLockerSessionResponse>("No White Label Session Token found"));
11911191
return;
11921192
}
11931193

11941194
string existingSessionEmail = PlayerPrefs.GetString("LootLockerWhiteLabelSessionEmail", "");
11951195
if (string.IsNullOrEmpty(existingSessionEmail))
11961196
{
1197-
onComplete(LootLockerResponseFactory.Error<LootLockerSessionResponse>("no session email found"));
1197+
onComplete(LootLockerResponseFactory.ClientError<LootLockerSessionResponse>("No White Label Session Email found"));
11981198
return;
11991199
}
12001200

@@ -1692,12 +1692,12 @@ public static void SetPlayerName(string name, Action<PlayerNameResponse> onCompl
16921692
{
16931693
if (name.ToLower().Contains("player"))
16941694
{
1695-
onComplete?.Invoke(LootLockerResponseFactory.Error<PlayerNameResponse>("Setting the Player name to 'Player' is not allowed"));
1695+
onComplete?.Invoke(LootLockerResponseFactory.ClientError<PlayerNameResponse>("Setting the Player name to 'Player' is not allowed"));
16961696
return;
16971697

16981698
} else if (name.ToLower().Contains(PlayerPrefs.GetString("LootLockerGuestPlayerID").ToLower()))
16991699
{
1700-
onComplete?.Invoke(LootLockerResponseFactory.Error<PlayerNameResponse>("Setting the Player name to the Identifier is not allowed"));
1700+
onComplete?.Invoke(LootLockerResponseFactory.ClientError<PlayerNameResponse>("Setting the Player name to the Identifier is not allowed"));
17011701
return;
17021702
}
17031703
}

0 commit comments

Comments
 (0)