Why can't I read my WWW responses in WebGL?

This WebGL platform is turning into a greater waste of space with every minute I waste on it. Why do you even bother having it when it is so utterly useless???

I use the exact same script on my server to send me text back in response to my WWW operation. The response works perfectly fine on Windows and OSX Desktops, Android and iOS devices, webplayer and in the editor… but when I build to WebGL I get an error “Unable to decode the response”.

Now what the hell is up with that?

Jeez… New Facebook Games platform? Fix this broken stuff first, man. Add new broken platforms later.

Case and point. 30 views and not 1 person, including anyone from Unity, can tell me how the WWW class receives it’s data in WebGL.

We have been using WWW in WebGL to successfully download both textual and binary data. One key thing is to make sure to check the done flag to make sure the request has finished before trying to read the data. The common way to do so is to use a coroutine.

Friendly tip. If you use a friendly tone and perhaps even post some sample code showing what does not work it is more likely you will get good answers.

Please note it works on all platforms EXCEPT this one. Thinking I didn’t use a coroutine… I think I would have noticed at some point over the past 2.5 years that this script has been in place that I missed using a coroutine :stuck_out_tongue:

As for my tone, I already apologised for that in the last thread I created. Yesterday. Getting really sick of all this WebGL bull have to deal with and 90% of my posts would consist out of “i’m sorry” until someone at Unity decides to get up off their ass and actually answer one of my questions.

Since posting this I have discovered a few things. First of all, POST data is simply ignored. All data sent to the script HAS to be done via GET. First Chrome refused to send the cookie AT ALL because sending a cookie is not allowed under any circumstances… Then I placed my cookie in a field and hacked the $_COOKIE super global array to contain the cookie that I sent it. But then it turns out that POST data is simply ignored when sent from WebGL (or Chrome. Haven’t tested in other browsers yet) so this means that the cookie I am sending the script is never sent and thus authentication always fails. Thank you for making that obvious, Unity.

Now that I am finally able to send my cookie to WP via a GET field and hack the $_COOKIE super global to contain my cookie, I now find that for some reason I cannot yet explain, Wordpress doesn’t send me back the login cookie when I log in… meaning I have to create my own cookie but by recreating the auth_login functionality of Wordpress to generate a cookie that (as far as I can see) matches the cookie WP itself generates, sending my cookie back to WP fails to authenticate so I am again stuck but this time due to something on WP’s end, not Unity’s…

But why am I stuck? And why did I keep getting those errors that I mentioned in the original post? Simple… as per USUAL, with absolutely NO THANKS to any help from Unity, I figured out the problem on my own… Thanks to all the data I send with the WWW call simply being ignored and never received by the script (_REQUEST is as empty as _POST), it means that all my define statements fail to get set and on the line where I test if a certain definition is true and quit if not, it quits there… meaning the script sends back the CORS headers and absolutely no data. Trying to turn the empty response into a byte[ ] causes the runtime error.

So solution to the answer asked above is: Don’t Use POST. WebGL does not support POST.

So now I am left with a new problem… how do I use GET to post a value that contains a =? I.e. www.site.com?cookie=user=admin ?
Right, so thanks to no POST support I have to first substitute my = with somethign else and then parse the string on the server before I can hack the $_COOKIE array. Fine, done. Next? Now I need to figure out how to get Wordpress to send back the cookie that it used to send but now, for some reason no longer does on this platform.

Guess I will have to make another thread and make more apologies for my tone when I ask why the web build of my app is the only platform that cant send OR receive cookies in the headers.

Oh hell, it can’t hurt… I apologise for my tone if I am coming across as totally pissed off. It is frustration talking. All this unnecessary hassle WebGL throws into the mix. Super bloody annoying, is what it is :frowning: Step 1, make your game. Step 2, deal with 3 million issues that the build platform introduces. Step 3. Publish after 9 months of fixing WebGL related issues.

This topic can now be closed as I found the answer: WebGL sucks. Simple.
Unfortunately, I can’t escape it so the frustration continues on… :frowning:

Ok. I may have missed something in all that info but I can assure you that you can use POST with a WWW object in WebGL because we are in fact doing so.

Here are some code snippets:
First, this is how we create the WWW object. The parameters are url, data and headers.
return new WWW(
Settings.OnlineBackendUrl + “/api” + api_route,
data,
headers);

data is serialized JSON data converted to bytes:
string json = JsonSerializer.ToJson(post_data);
byte[ ] data = Encoding.UTF8.GetBytes(json);

and headers are:
new Dictionary<string, string>
{
{“Accept”, “application/json”},
{“Content-Type”, “application/json; charset=utf-8”}
};

Note sure if it helps you but I though it was worth mentioning that POST does work.

Hi, thanks for the feedback. I managed to get POST working yesterday also. For some reason it seems you MUST specify the headers param or else it comes up empty. All other platforms work with either WWW(url) or WWW(url, data). Seems WebGL is the only one to actually REQUIRE the headers.

I stumbled upon this fact when I found some sample code on the forum on how to properly set the CORS response on the php script. I have never heard of the OPTIONS post type but apparently WebGL calls your script with that method (not sure if it calls it FIRST or just calls it but for whatever reason I need to set some of my headers when my script is called using the OPTIONS method and the rest when it is called using the POST or GET method. Long story short, both GET and POST now work due to me setting CORS headers during the OPTIONS … thing…

I am still not sure what the OPTIONS mode does or why it is used. All I know is that the sample code I used contains a 'die()" command and if I leave it in place I get errors but when I take it out, the script works well for a while, till I start getting errors. Then I put it back in, press the same button and my errors are gone, till the others return… at which point I comment out the die() again and those errors are gone again, until the others come back again… Nice one. so should it go or should it stay? Both result in the code working till it doesn’t. WTF is this OPTIONS thing and why must I do what exactly inside of it and why can I not find any of this info in the docs?

Right now I have found ways to bypass the restriction that I may not set a cookie header when I contact my script but I still need to know how to send a cookie BACK. Again, no matter what headers I set, I always only see the same 4. The Set-Cookie one is the one I need and that simply never arrives at the game.

That and what the hell the whole OPTIONS post type is for and what should and what should not be set during that phase and whether or not this means my scripts get run twice every time I call them with a WWW call or how does the OPTIONS post type work? where can I find THIS info?

OPTIONS requests are sent by the browser to check CORS authentication before sending the real request. This is not anything done by our WebGL code, but this is basic security validation needed to allow code running on a web page to connect to other hosts, and performed by the browser. This is documented in full detail here: Fetch Standard , but what it comes down to is that non-trivial http requests will result in a pre-flight OPTIONS request with the set headers, and decide whether or not to allow the request based on the server’s response and the Access-Control-* headers returned by the server.

1 Like

Hi there. That was just beginning to make sense before you completely lost me. Guess Karma is now paying me back for all those years of writing walls of text by you linking me to a novel to read just to figure out how to get my php script to run and send me back a cookie :frowning:

I want to just copy the code I got from that other thread here on the forum and just ask you about that exit() thing. When I do NOT have it in Chrome tells me I don’t have the relevant access control headers in place. If I add it in and kill my script then my script runs perfectly… until at some random point (I think after a page refresh) suddenly having it in there makes my script die all the time and no responses are sent back to my game unless I comment it out… What is up with that?

Back in the days of the WebPlayer, the web player did not work unless we had a crossdomain script in the root. That script you gave us, I placed it in my root and the WebPlayers worked. Thank you very, very, very much for that! Now with this new WebGL build, can’t you give us a similar piece of code we can just copy paste into our scripts to make it work? …or is every single script in every single game going to be it’s own little challenge to make that particular script work? Cause I got to tell you, that backs my argument that WebGL is a shitty platform to build for…

Please give me some good news and say there is a generic piece of code I can copy paste like this:

<?php

function cors() {
 
    // Allow from any origin
    if (isset($_SERVER['HTTP_ORIGIN'])) {
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }
 
    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
 
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            header("Access-Control-Allow-Methods: GET, POST, OPTIONS");        
 
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
        exit(0);
    }
}
cors();

Two more (hopefully quick and simple questions) before I go read the entire manual for all things security and become a bonafide expert in it before I can have my scripts work again…

  1. When you say the browser does a pre-flight OPTIONS request… it calls my script, right? My script containing all my headers and other scripts to run and files to link in and constants to define and database wrappers that get initialised and prepped etc etc etc… It does all of that and then afterwards call it all again? So all scripts are run twice and all output from the first run is simply discarded? Or does this pre-flight mode somehow know to only run the first 5 lines or 8 lines of my script? Or does it NOT run my script but instead only look for certain commands inside the script? This is the thing I don’t get about the pre-flight request… Double execution or only partial execution?

2.Oh bother, I forgot the other question… All I recall was that this was the simple question :stuck_out_tongue: Anyway, will ask later. :slight_smile:

Oh yeah, now I remember…

I spent days trying to get this CORS stuff to work so I could build my project from Unity and when the app opens I connect directly to my online website. After failing miserably to get this to work, I finally decided to see what would happen if I actually uploaded the build to my website and run it from the same domain… Now suddenly I get errors that prevent the entire game from actually loading at all… Again I no longer have access permissions to run my scripts from the very domain that it is on and accessing data from but not only does it now throw me errors while my game is running, now the entire game refuses to even load at all… All I see is the loading progress meter. Sometime loading, othertimes just standing at 100% and not moving. In no event can I actually see my game any more.

Who do my WebGL builds only work from my local computer but not from the domain it is accessing php scripts on? How is it that CORS determine cross domain communication and yet I can’t run my games from it’s own domain?

If there are any Greek speaking individuals on this forum, could you please translate Fetch Standard for me?
Thanks

Well I am not familiar with how CORS can be handled by PHP but in my case the back-end is using ASP.NET Web Api which can be configured to handle CORS. Then the OPTIONS request is automatically handled but it does not execute the actual API before getting the real POST request. I suppose something similar could be done when using PHP.

On my end, I have never worked with the ASP.NET Web API so I have no idea what you mean :stuck_out_tongue: I m assuming you mean enabling CORS in Apache. i heard that was a thing…

If so, unfortunately that is not an option for me as my kits need to work on websites that use shared hosting. I.e. if you buy my login kit you just install it on your website and you have instant Wordpress authentication of your identity and access to your website details on all platforms. The only thing you need to do is give my plugin your website URL, that is it. No further configuration needed. So if some guy with an account at freewebsites.com has a Wordpress website there and wants to use my kit and do a WebGL build… they don’t have access to the php configuration files or the ability to restart Apache to enable it so they are sh*t out of luck.

I can’t believe doing a web build is this complicated now and the only advice I get from Unity is to go to some external site and read an entire manual of Greek babble until one day it starts to make sense and THEN I can come back to Unity and finally make my build.

But thanks for the suggestion. If I misunderstood what you meant, please correct me :slight_smile:

Well, after alexsuvorov took some time out of his day to try and help me I have reached the following status:
Crossdomain, just forget about it. I can’t get my projects to work using crossdomain (to be exact, run it from home but use my online website)

…but, if I upload the build to my website then it works just fine. POST, GET, both of them… Just cut out CORS from the mix and I am good to go.

Apparently, my setup is a non standard one also. I need to modify the index.html file Unity generates to add “gz” after the filenames of the files it imports or else it can’t find them. Strange but there you have it. So this CORS thing is a bloody mystery still and every single time I set the cookie, Chrome b*tches and moans about refusing to do it because it’s unsafe but… it works non the less.

So the lesson I am taking away from this is this:
Develop in Unity, upload to test the build, never test a WebGL build that uses WWW from your local system.
Simple rules to live by and all the frustration is gone. I can live with that :smile: