5

I'm using zapworks studio to develop an AR experience. It uses Z.ajax to make the ajax calls. I make a GET request and a POST request. I'm also using smileupps to host couchdb(they have free hosting). Here's the CORS configuration:

credentials: false; headers:Accept, Authorization, Content-Type, Origin; methods: GET,POST,PUT,DELETE,OPTIONS,HEAD; origins: *

Everything works fine when launching ZapWorks Studio on windows. When scanning the zapcode with an android device, however, the post ajax call fails. Only the post. I am using basic authentication. I enforce that only the admin can manage the database on couchdb. I can access the host from both the desktop and the phone from a web browser to do everything manually.

I tried everything I could of to solve the problem: remove authentication, change the CORS configuration...nothing works. I thought it was an issue with CORS but everything works fine on windows and on the mobile just the POST fails...I keep getting a status code of 0.

EDIT - New info, testing on apitester also works on the desktop and mobile.

EDIT - Here's the zpp to show the logic

EDIT - Tried with REST Api Client on my phone and it worked as well. This can only be a CORS issue or something with zapworks. Weird that it works on windows but not on the phone.

EDIT - I found out what the problem is, but not how to fix it. So I set a proxy to debug the requests made from zapworks studio following this tutorial. It seems that it does a preflight request but gets the response

"HTTP/1.1 405 Method Not Allowed"

even though the payload is

{"error":"method_not_allowed","reason":"Only DELETE,GET,HEAD,POST allowed"}.

Here's the request:

OPTIONS /ranking HTTP/1.1
Host: somehost.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: null
User-Agent: Mozilla/5.0 (Linux; Android 8.0.0; SM-G950U1 Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 Mobile Safari/537.36
Access-Control-Request-Headers: authorization,content-type,x-requested-with
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
X-Requested-With: com.zappar.Zappar

and the response:

HTTP/1.1 405 Method Not Allowed
Server: CouchDB/1.6.0 (Erlang OTP/R15B01)
Date: Mon, 18 Jun 2018 21:22:12 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 76
Cache-Control: must-revalidate
Allow: DELETE,GET,HEAD,POST
Access-Control-Expose-Headers: Cache-Control, Content-Type, Server
Access-Control-Allow-Origin: null
Connection: keep-alive

{"error":"method_not_allowed","reason":"Only DELETE,GET,HEAD,POST allowed"}

which clearly shows that POST is allowed...

On the windows side, there doesn't seem to be a preflight request for some reason and my guess is that's why it works. Now the question is how do I configure CORS on couchdb to work on android. These are the configurations available:

enable_cors: true
credentials: false
headers:Accept, Authorization, Content-Type, Origin
methods:GET,POST,PUT,DELETE,OPTIONS,HEAD
origins:*

This is the code:

const Open_SansRegular_ttf0 = symbol.nodes.Open_SansRegular_ttf0;

parent.on("ready", () => {
    const Plane0 = symbol.nodes.Plane0;

    let ajaxParameters : Z.Ajax.Parameters = {
        url: "https://something.smileupps.com/test/_all_docs?include_docs=true",
        headers: {"Authorization": "Basic my64encoding"},
        method: "GET",
        timeout: 3000
    };

    // Perform the AJAX request
    Z.ajax(ajaxParameters, (statusCode, data, request) => {checkRequest(statusCode, data);});

    ajaxParameters = {
        url: "https://something.smileupps.com/test",
        headers: {"Content-Type":"application/json", "Authorization": "Basic my64encoding"},
        method: "POST",
        body: '{"name" : "asdasd", "something": 234}',
        timeout: 3000
    };

    Z.ajax(ajaxParameters, (statusCode, data, request) => {checkRequest(statusCode, data);});


});

function checkRequest(statusCode, data) {
    if (statusCode === 0) {
        Open_SansRegular_ttf0.text("Unable to connect - check network connection.");
        console.log("Unable to connect - check network connection.");
        return;
    }

    if (statusCode < 200 || statusCode >= 300) {
        Open_SansRegular_ttf0.text("HTTP request failed: " + statusCode);
        console.log("HTTP request failed: " + statusCode);
        return;
    }

    // Attempt to parse the data returned from the AJAX request as JSON
    let parsedData;
    try {
        // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
        parsedData = JSON.parse(data);
    } catch (e) {
        Open_SansRegular_ttf0.text("Unable to parse JSON: " + e);
        console.log("Unable to parse JSON: " + e);
        return;
    }

    return parsedData;
}

EDIT Here's the request on windows

Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US
Authorization:Basic mybase64encoding
Connection:keep-alive
Content-Length:37
Content-Type:application/json
Host:http://something.smileupps.com/test
Origin:file://
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ZapWorksStudio/4.0.4-stable Chrome/58.0.3029.110 Electron/1.7.9 Safari/537.36
X-DevTools-Request-Id:3680.9
X-Requested-With:XMLHttpRequest

and the response:

Access-Control-Allow-Origin:file://
Access-Control-Expose-Headers:Cache-Control, Content-Type, ETag, Server
Cache-Control:must-revalidate
Content-Length:95
Content-Type:text/plain; charset=utf-8
Date:Mon, 18 Jun 2018 21:36:22 GMT
ETag:"1-512f89feb3d0a88781119e772ec6fd7b"
Location:http://something.smileupps.com/test
Server:CouchDB/1.6.0 (Erlang OTP/R15B01)

No preflight.

savram
  • 500
  • 4
  • 18
  • is host accessible from phone ? or only from computer your are working on ? – Alberto Cappellina Jun 15 '18 at 14:28
  • yea the host is accessible from the phone. I can type the url and do everything manually. – savram Jun 15 '18 at 14:39
  • Are you sure Is this ok Access-Control-Allow-Origin: null ? and this Access-Control-Allow-Origin:file:// ? It's not possible to perform a CORS request with those headers. – Emeeus Jun 23 '18 at 20:43
  • Try setting this header in server: Access-Control-Allow-Origin: * and read this https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin – Emeeus Jun 23 '18 at 20:53
  • OPTIONS is a method, just like POST, GET, PATCH... etc. So the response is saying that OPTIONS is not allowed, and therefore your preflight requested is not accepted by this server. https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS – Victor Lia Fook Jun 25 '18 at 00:02
  • Supposing, of course, that the server responses are coherent – Victor Lia Fook Jun 25 '18 at 00:12

1 Answers1

0

Your problem is in the request: Origin: null is usually what you get when the Web page containing the xhr request is opened with the file: rather than the http or https protocol. You won't get any successful CORS request with such an origin.

Aurélien Bénel
  • 3,775
  • 24
  • 45
  • I added the code that shows the logic. How do I fix this problem? There is nowhere I define how the xhr request is opened. – savram Jun 19 '18 at 16:10
  • Do you have any idea on how is served your javascript? On a traditional CORS setting, the `Origin` header would be set by the browser according to the URI of the HTML page. I suppose then that Zappar doesn't do its job... Maybe a setting to change? or a different run mode to choose? – Aurélien Bénel Jun 19 '18 at 16:35
  • I updated the post with the request and response that happens on windows. You are correct about the file:, but on windows it works and I see no preflight. Weird. – savram Jun 19 '18 at 18:16
  • On Windows, `Origin:file://` shows exactly what I said above: there's really a problem in the way the origin is handled by your environment (Zapwork studio?). Please check in your development/test environment that there is not in the settings a way to define the port of the Web app. Check also if there are not development and production modes. They might differ in the way they serve the HTML and JS of your app. – Aurélien Bénel Jun 19 '18 at 20:40
  • From this post: https://stackoverflow.com/questions/9103876/cors-cookie-credentials-from-mobile-webview-loaded-locally-with-file?noredirect=1&lq=1 and this one: https://stackoverflow.com/questions/5138057/cross-origin-resource-sharing-and-file?noredirect=1&lq=1 it seems that mobile apps use file://, so it's not a problem with ZapWorks Studio, or maybe I'm wrong...they say one solution is to use a web server to hit the web service on the comments of the first link. But I don't get it, can you explain better? – savram Jun 20 '18 at 18:06
  • Found this: https://medium.com/netscape/hacking-it-out-when-cors-wont-let-you-be-great-35f6206cc646 . I think I get the idea now. Seems to be the only solution I got. – savram Jun 20 '18 at 19:49
  • Yup this https://github.com/Rob--W/cors-anywhere/ worked for me. I don't like it, but until ZapWorks Studio team implements proper origins it will do. – savram Jun 21 '18 at 18:18
  • @savram Nice to know that your problem is fixed. – Aurélien Bénel Jun 21 '18 at 21:39