Search Unity

WebGL WWW security (Cross-Origin Resource Sharing) help please

Discussion in 'Web' started by crushforth, May 26, 2015.

  1. crushforth

    crushforth

    Joined:
    Jul 22, 2010
    Posts:
    113
    I'm getting the following error message whilst attempting to login via our server endpoint:

    XMLHttpRequest cannot load ???????. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '????????' is therefore not allowed access. The response had HTTP status code 404.

    Based on this http://docs.unity3d.com/Manual/webgl-networking.html and a bit of searching online, we tried adding the following headers to the login page:
    Code (csharp):
    1.  
    2. "Access-Control-Allow-Credentials": "true",      
    3. "Access-Control-Allow-Headers": "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time",       "Access-Control-Allow-Methods": "GET, POST, OPTIONS",      
    4. "Access-Control-Allow-Origin": "*",
    5.  
    and I've also tried adding the headers to the WWW request in code:

    Code (csharp):
    1.  
    2. Dictionary<string, string> headers = new Dictionary<string, string>();
    3.  
    4. #ifUNITY_WEBGL
    5. headers.Add("Access-Control-Allow-Credentials", "true");
    6. headers.Add("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time");
    7. headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    8. headers.Add("Access-Control-Allow-Origin", "*");
    9. #endif
    10.  
    11. WWW www = new WWW(url, null, headers);
    12.  
    Should these headers be set on just the server response or the client's request?

    Any help would be greatly appreciated.
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    These headers should be set to the server's response.
     
    Dustin-Horne likes this.
  3. crushforth

    crushforth

    Joined:
    Jul 22, 2010
    Posts:
    113
    Thanks for clearing that up. It's not working for us with the headers on both. I'll do a new build with just the headers on the server and a completely normal WWW request.

    We're also beginning to wonder if we even have this enabled on the server or not. We're using wpengine.com so maybe we have to do some fiddling around to turn everything on.
     
  4. crushforth

    crushforth

    Joined:
    Jul 22, 2010
    Posts:
    113
    Just in case anyone else encounters this issue. Don't send the headers as part of the request. Get the server to send them as part of the response. We had to enable CORS in our rails app before anything would start working.

    You only get a subset of the www.responseHeaders back that you would normally get via a WWW request in the WebPlayer. We weren't getting back the HTTP 'status' header but it seems like you can tell the server to correct this using :

    "Access-Control-Expose-Headers" : "Status" (haven't actually tested this yet so this maybe incorrect)
     
  5. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yep, that's because CORS is meant to stop cross domain requests. The reason it has to be in the response is because it's the server telling the browser "yes, we will trust and accept requests from you and your domain origin". Note that you should also be able to specify which origins you trust (at least you can in the WebApi CORS library). That way you don't just blindly enable CORS and open your endpoint up to the world. You just limit it to the domain(s) your WebGL app is being served from.
     
  6. jdbenitez

    jdbenitez

    Joined:
    Feb 11, 2014
    Posts:
    7
    i agree the response of liortal: "These headers should be set to the server's response."
     
  7. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    As others wrote, you need to set up the headers on the server's response.

    This is correct. From the docs page you linked:

    "Note that WWW.responseHeaders is limited to a subset of the actual response headers, according to 7.1.1 of the CORS specification."

    Nice - I actually did not know about "Access-Control-Expose-Headers".
     
  8. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    309
    So my master plan to let users download images from their dropbox account using WWW-class is not going to work then I guess as I can't set the servers response?

    Or am I misinterpreting the info above?
     
  9. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    1) If your WebGL main page is located on the same domain where the requested images are hosted, then WWW request should work as expected.

    2) If your WebGL main page is located on another domain, then you can create a hidden iframe with an html hosted on the same domain where the images are hosted. Such an iframe will be able to download the images using XMLHttpRequest and transfer them back to the WebGL application on the main page (using postMessage for page interaction and jslib plugin for interaction with WebGL)

    3) As an alternative solution, you can always setup an intermediate proxy server, that will proxy your requests to the server in question, and then add proper CORS to the response.

    P.S. If talking about a specific domain (i.e. dropbox.com or dl.dropboxusercontent.com) you should first examine its response, maybe proper CORS headers are already set there.
     
    Last edited: Jan 19, 2016
    sama-van, guneyozsan and Mikael-H like this.
  10. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    309
    Thank you so much for answering, this has been having me tearing my hair off for a few days :)
    I am a pure c# coder/math guy with no experience with the web at all so I may not understand everything you write about...

    1) I read about this before but this is only an option if I host the WebGL app on dropbox which I was hoping not to do. But it does work if you change the image link url a bit. Still, this only allows for users to upload images to dropbox so it isn't optimal.

    2) Interesting.. So I could have the page where I want it to be and keep just the WebGL app on dropbox?

    3) Umm you kinda lost me there :) This is probably out of my comfort zone anyway haha


    What I really want to do is just let a user upload images to my WebGL app. I need to be able to read individual pixels because I will be running some image analysis magic o them. Going the path via dropbox was just a workaround because I couldn't figure out a way to load them from the users harddrive using WebGL but maybe there is a solution for that?
     
  11. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Rather vice versa. You can have your WebGL application where you want, and create a helper html page on dropbox (i.e. https://dl.dropboxusercontent.com/u/12345678/imageloader.html). You can load this imageloader.html in a hidden iframe on your page (invisible to the user) and transfer the loaded images to the WebGL application page using postMessage. The iframe will be able to download the images directly because it shares the same domain with them.

    Actually this is not complicated. If your got node.js or at least php available on your hosting server, then you can just download any proxy available on the net. All you have to do is to append proper CORS headers to the proxied response and prefix your request url with the proxy address.

    Yes, of course there are ways to load images from the user hard drive to the WebGL application (assuming that the user will select the files himself through the browser dialog). There is even a way to save the processed images back to the user hard drive ;) This is a bit out of the scope of the current discussion, but you can create a separate thread for that, describing in details what exactly you are trying to achieve.
     
    Last edited: Jan 21, 2016
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    To expound on this a bit, here's a sample of some JavaScript that uses postMessage to send data to an iFrame. It may need to be tweaked a bit to support all browsers... contentWindow might only work in IE:
    Code (csharp):
    1.  
    2. if (target && target.contentWindow) {
    3.  target.contentWindow.postMessage(message, '*');
    4.  }
    5.  
    In this case "target" is a reference to the iFrame element. On the receiving side it looks something like this:

    Code (csharp):
    1.  
    2. window.addEventListener('message', messageHandler);
    3.  
    messageHandler is just a function that's executed and from there you can verify the source (origin):

    I do something like this:

    Code (csharp):
    1.  
    2.   var messageHandler = function (e) {
    3.       var message = e.data;
    4.  
    5.       if (sourceWindow == null)
    6.         sourceWindow = e.source;
    7.  
    8. };
    9.  
    No I'm not verifying origin because I'm using this in an internal only application. Also, by capturing e.source, you can use that reference to use sendMessage and kick messages back to the sending page / frame. If you get very deep into it I can share a bit more code with you as I've created a complete event and command binder that I use to marshal commands and events along with data back and forth between windows using sendMessage.
     
  13. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    309
    You're absolutely right, I started feeling that I was hijacking the thread, sorry about that...

    I started a new thread for my specific issue of loading an image in WebGL from harddrive instead:
    http://forum.unity3d.com/threads/ho...from-their-harddrive-into-a-webgl-app.380985/

    Thank you so much @alexsuvorov and @Dustin Horne for your help, I think in the future I will look into your online solutions to load images from e.g. dropbox, onedrive etc as well.
     
    Dustin-Horne likes this.
  14. Deleted User

    Deleted User

    Guest

    Just to help anyone finding this thread: the Access-Control-Expose-Headers header should be set on the primary response call alongside the headers you want to access, NOT on the pre-flight OPTIONS response.

    Cheers!
     
    Mikael-H likes this.
  15. coutlass-supreme

    coutlass-supreme

    Joined:
    Feb 21, 2014
    Posts:
    22
    Im having CORS problems on the same domain. Do you know what could be happening? Im using chrome and WebGL

    Failed to load https://thisisnotanumber.org/rastreadoras/media/imagen.jpg: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.thisisnotanumber.org' is therefore not allowed access.
     
    SplenShepard likes this.
  16. ikv007s

    ikv007s

    Joined:
    Mar 9, 2014
    Posts:
    11
    add
    <?php
    header("Access-Control-Allow-Origin: *");

    add this to php file hosted on the server.Both get and post request started working
     
  17. Railon23

    Railon23

    Joined:
    Jan 30, 2014
    Posts:
    32
    Hi,
    I've created an application with this script (https://forum.unity.com/threads/raw-data-export-example-script.460957/) to request a Raw Data Export of the Unity Analytics data. This works fine in the editor and also in the .exe application.
    If I build a WebGL build and put it on our server, I get the "Unknown Error". I tried some things with .htaccess on my end, but I read that it must be done on the server. So the question is if Unity Analytics (https://analytics.cloud.unity3d.com) supports CORS, right?
    Any idea what I could do next?
    Thanks
     
  18. uniteiro

    uniteiro

    Joined:
    Mar 11, 2014
    Posts:
    12
    thankyou!! solve my problem
     
  19. Sakuwwz

    Sakuwwz

    Joined:
    Nov 5, 2018
    Posts:
    50
    Hi, I'm having the same issue nut only in Firefox... Do you know how to fix it?
     
  20. papayalabs

    papayalabs

    Joined:
    Apr 5, 2020
    Posts:
    1
    Hi, I have hosted my game in for example https://www.mygame.com and want to load images from Amazon S3. I already put CORS headers on Amazon S3 bucket but still does not work. But if I enable CORS on my firefox browser it works fine but my game is in a web server not in my localhost. I dont understand. Please any help? Thanks!!
     
    asmanjitha and riomoko like this.
  21. Toscan0

    Toscan0

    Joined:
    Oct 9, 2018
    Posts:
    11
    The real MVP
     
  22. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,734
    Eh what do you mean? Into the index.html file?
    How about the AmazonS3 settings?
    Should it be as set below?
    upload_2021-9-3_17-17-50.png
     
  23. asmanjitha

    asmanjitha

    Joined:
    Apr 6, 2017
    Posts:
    3
    I'm having the same problem. Can someone suggest a solution?
     
  24. ErkanAkin

    ErkanAkin

    Joined:
    Oct 26, 2019
    Posts:
    8
    I have same problem too. Can someone please help about that.
     
  25. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,734
    Yup and still didn't resolve that one either :D
     
  26. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    150
    Anyone try this method out

    2) If your WebGL main page is located on another domain, then you can create a hidden iframe with an html hosted on the same domain where the images are hosted. Such an iframe will be able to download the images using XMLHttpRequest and transfer them back to the WebGL application on the main page (using postMessage for page interaction and jslib plugin for interaction with WebGL)


    some examples of code perhaps ?
     
    sama-van likes this.