Search Unity

WWW and UnityWebRequest issue in WebGL

Discussion in 'Web' started by donnysobonny, Apr 16, 2017.

  1. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    Hey all,

    I'm currently polishing off a game that we're about to release the web-build for, and i've been trying to get the game to work nicely with the error reporting disabled (for the extra performance). There is one remaining issue, that I will likely have to implement a work-around for.

    Code (CSharp):
    1.         private IEnumerator handleRequest(WWW www, Request request) {
    2.             yield return www;
    3.  
    4.             Action onComplete = request.getOnComplete();
    5.             Action<JsonData> onSuccess = request.getOnSuccess();
    6.             Action<string> onError = request.getOnError();
    7.  
    8.             try {
    9.                 if(!string.IsNullOrEmpty(www.error)) {
    10.                     if (www.responseHeaders != null && www.responseHeaders.ContainsKey("STATUS")) {
    11.                         //extract the error from the status
    12.                         string[] parts = www.responseHeaders["STATUS"].Split(' ');
    13.                         if (parts.Length < 3) {
    14.                             throw new Exception(www.error);
    15.                         } else {
    16.                             string error = "";
    17.                             for (int i = 2; i < parts.Length; i++) {
    18.                                 error += parts[i] + " ";
    19.                             }
    20.                             throw new Exception(error);
    21.                         }
    22.                     } else {
    23.                         throw new Exception(www.error);
    24.                     }
    25.                 } else {
    26.                     JsonData data = JsonMapper.ToObject(www.text);
    27.                     if ((bool)data["error"] == true) {
    28.                         throw new Exception((string)data["error_message"]);
    29.                     } else {
    30.                         if (onSuccess != null) {
    31.                             onSuccess(data);
    32.                         }
    33.                     }
    34.                 }
    35.             } catch(Exception ex) {
    36.                 if (onError != null) {
    37.                     onError(ex.Message);
    38.                 } else {
    39.                     Debug.LogErrorFormat("ERROR ({0}): {1}", www.url, ex.ToString());
    40.                 }
    41.             }
    42.  
    43.             this.processingRequest = false;
    44.  
    45.             if(onComplete != null) {
    46.                 onComplete();
    47.             }
    48.         }
    In this code, the internal processing of the first line yield return www; throws an uncaught exception in webgl builds when the server responds with something other than a 200 OK response. In other platforms (tested in standalone builds and android), no exception is thrown, and I am able to handle non-200 responses in the later lines of that code. The same happens when UnityWebRequest is used, and yield return www is replaced with the UnityWebRequest.Send method.

    So the issue here is because it causes an un-catchable exception:
    • i can't catch the exception, because it is handled in the internal co-routine procedure and you can't put a "yield return X" within a try/catch block
    • i can't handle a non-200 response in the later lines of the above code
    • it causes the error popup in webgl builds saying that there is an error and errors are disabled, and causes the game to stop running
    It's very common for apis to not respond with 200 and for this to be something that you want to handle. For example, responding with 401 and knowing to notify the user that they need to authenticate. So it's pretty important that we're able to handle non-200 responses in webgl builds, without it causing the above issue.

    Let me know if you need further information
     
  2. yuliyF

    yuliyF

    Joined:
    Nov 15, 2012
    Posts:
    197
    try/catch doesn't work on WebGL. Try to log it as Debug.Log("result: "+ www.error); and look to browser console
     
  3. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    Try/catch does work in webgl... exceptions and try/catch are both available in javascript and are used regularly throughout my code without any issues. The issue is the yield return www line (which would be yield return www.Start() for a unity web request) causes the exception within unity's own internal code. There is no way for me to catch the exception, or log it as you have suggested, therefore it will always be treated as an unhandled exception (causing webgl builds with error reporting disabled to fail).
     
  4. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    This sounds like a bug. Can you file a bug report with a repro case, and post the the case number here?
     
  5. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
  6. donnysobonny

    donnysobonny

    Joined:
    Jan 24, 2013
    Posts:
    220
    Apologies, it looks like I have jumped the gun a little bit. After building and testing the stripped-back project submitted along with the bug report it does in-fact work, suggesting the bug isn't in relation to the yield line, but something else.

    I've attached a unity package with the minimum scripts etc that can be used to reproduce. Ultimately, the game i'm working on has a web-backend for persistent data using a custom web framework (called extorio). There's a simple set of scripts (in the "extoriounity" folder) that are used to communicate with extorio apis.

    If you build and run the attached project with error reporting set to full or explicit it works fine and doesn't report any problems. The strange thing is if you build and run the exact same project with error reporting set to "none", the alert/dialog pops up saying that there is an error which cannot be caught because errors are disabled... (even though no errors were generated when error reporting was enabled...?) I'm not 100% sure now if this a bug or maybe something that I am doing wrong... either way it seems like strange behavior.

    Your help would be greatly appreciated.

    UPDATE

    I've added a bunch of Debug.Log calls to the Api.cs script, to try and work out exactly how far through the code the request gets before it causes the error in the webgl build (with errors disabled). I've attached the updated Api.cs script here.

    The output in the browser shows something quite peculiar: "test21" is output, which is expected. Directly after this, an exception is thrown within the try/catch block, so we would expect "test26" to be output, but it doesn't get output. Here's a snippet of what I see in the console:

    error.png
    This seems very odd... it's almost as if the exception thrown after "test21" is output isn't caught, even though it is within a try/catch block?

    UPDATE 2

    Okay i've managed to isolate the issue. I've attached the updated ReproduceBug.cs script here. Ultimately, trying to both throw and catch an exception within the Ienumerator used to handle a WWW or UnityWebRequest seems to cause the error mentioned in the original post, in webgl builds with errors disabled. Let me know if you want me to file another bug report?
     

    Attached Files:

    Last edited: Apr 18, 2017