Post request converts to Options request when using WebGL

Hi,

It’s great that unity developer teams added webgl building option.
I chose webgl platform for my next release and I hope it works correctly.
The original project was a mobile client/server application.
The mobile client was sending POST requests to the server for login and stuff and the server responds with JSON response.

        postHeader.Add("Content-Type", "text/json");
        postHeader.Add("Content-Length", jsonString.Length.ToString());
        postHeader.Add("_sessionKeyS", hash);
      
        var request = new WWW(url, encoding.GetBytes(jsonString), postHeader);

The problem is that after porting the stuff to web gl, the request/response sequence did not work correctly.

When I checked the apache access log I found out this

But normally it should be POST /api/login.php
I am not sure how to handle this situation.

Any help or hint is greatly appreciated.
Thanks for advance.

I found the error, but I am not sure of the solution yet.
In php this if fails.

if(isset($headers['_sessionKeyS'])){

Even thought the webgl client sets it like that

postHeader.Add("_sessionKeyS", hash);

I figured it out!
Since I am sending a custom header, there is a call called ‘prelight’ that goes to the server.

I added this to my PHP and it handles the prelight then sends the API calls correctly.

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();

Hope it helps someone.

1 Like

Yes, all http traffic from WebGL to host other then the one hosting the content will do CORS validation, which uses OPTIONS requests to validate permission to access the data. This is a security measure implemented by browsers.

3 Likes

I’m using django with corsheaders, and when I WWW Post to /client/post it is receiving it – but it is receiving it as empty POST data. if I check for OPTIONS at /client/post it returns an error, “wsgi request did not have header “OPTIONS””.

Does anyone know what’s going on here? Why would my WWWForm, which sends regular POST data and works fine from desktop application, fail when it’s deployed as WebGL? If it is converting the POST to OPTIONS for the server to prelight the call, why does the server not see OPTIONS?

thanks!

i have this same issue. webgl

unity side

        request.SetHeader("Access-Control-Allow-Credentials", "true");
        request.SetHeader("Access-Control-Allow-Origin", "*");
        request.SetHeader("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time,Authorization");
        request.SetHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");

        request.SetHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        request.SetHeader("X-Requested-With", "XMLHttpRequest");

        request.SetHeader("Authorization", "Bearer " + StaticUtilities.BrearerToken);

server side

  app.post('/Api/v1/Game/Login/', Security.verifyToken, function (req, res) {
    res.setHeader('Content-Type', 'application/json');
    res.setHeader("Access-Control-Allow-Credentials", "true");
    res.setHeader("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    res.setHeader("Access-Control-Allow-Origin", "*");

    let UserName = req.body.UserName;
    let Password = req.body.Password;
    let DeviceUUID = req.body.DeviceUUID;
    let IP = req.body.IP;
    let DeviceName = req.body.DeviceName;
    let DeviceRam = req.body.DeviceRam;
    let DeviceCpu = req.body.DeviceCpu;
    let OperatingSystem = req.body.OperatingSystem;
    let GraphicsDevice = req.body.GraphicsDevice;
    Login(UserName, Password, IP, DeviceName, DeviceRam, DeviceCpu, res);
  });

Is this with a recent version of Unity?

thanks for replying yes it is but i realize the problem was i didn’t handle option in the server side

var cors = require('cors');
app.options('*', cors());//to support webgl request and resolve post routing to option