0

To preface this, I am working on a pull request for Syncthing - a continuous file synchronization software. The pull request will allow for an url to be seen for all connected remote machines from the GUI.

The problem I am having is the OPTIONS request is failing to the remote machines. Before the program displays an url to the remote machine, the maintainers have requested that that the GUI verifies the machine will allow the user to visit the remote machine GUI (GET request will fail if the machine has set authentication, so verifying an OPTIONS response is good enough). I can verify the CORS is setup properly. I can even send a curl request and go to the remote machine through the browser, but for whatever reason, the javascript OPTIONS request receives a network error. When I look at the remote machine that will respond to the request, no matter curl, javascript, or browser, it's sends a 201 request back. However, when I look into the chrome network console of the machine sending the request, I see the options request fails, but later on, it seems the request succeeds. My intuition was that the request timeout before the machine sends a valid response and retries. Still, after setting a longer options request header, it does not change result as if the timeout duration is not affecting the error.

This javascript snippet comes from the GUI using angular. It uses angular $http library.

$scope.probeAddress = async function (address, successCallBack) {
        try {
            var response = await $http({
                method: "OPTIONS",
                url: address,
                timeout: 40000,
            });
            return response.$$state.status >= 200 && response.$$state.status < 300;
        } catch (error) {
            console.log(error);
        }

}

It responds with a network error, response.$$state = 0.

A picture of the chrome network console. I think it is currently sorted by duration. If sorted in order of received, the red errors would be first. I do not know why the OPTIONS request are retried, but I definitely did not write the code to retry. Both IP Addresses have authentication setup. chrome network console sorted by duration

A log of one of the machine receiving requests. As you can see, both OPTIONS request receive a 204 response. It says the response was sent in .02ms, while the browser only waits for 112mslogs remote machine verify that it receive the request and sent a 204

Rahmi Pruitt
  • 569
  • 1
  • 8
  • 28
  • 1
    OPTIONS requests are usually done automatically by the browser when accessing cross origin resources - you don't need to make that request yourself (and it won't help CORS even if you do) – Jaromanda X Oct 19 '20 at 01:57
  • Also `$http` is asynchronous and you need to work with the promise it returns. You can't make the `return` as you are trying now because you are returning before request completes. See [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – charlietfl Oct 19 '20 at 02:03
  • @charlietfl I change the code with async await. I still see a network error. My bad for noob mistake. – Rahmi Pruitt Oct 19 '20 at 02:28
  • Ok but as mentioned above you never need to do your own OPTIONS request. Read up on how CORS works ( easy topic to research the basics on) – charlietfl Oct 19 '20 at 02:31
  • @charlietfl I am familiar with CORS. I don't have to do a GET because request send a preflight OPTIONS before. Still, as mention, a GET request does not make sense here because it is impossible to succeed due some GUIs requiring the user to submit username and password. Although a failing GET request would tell if the machine will allow users to visit it and eventually authenticate, it's good practice to not write code that produces errors (so future developer will not think a bug exists). An OPTIONS request gives me what I need without authentication or causing an error. – Rahmi Pruitt Oct 19 '20 at 02:47
  • Try a HEAD request then perhaps? – charlietfl Oct 19 '20 at 02:49
  • With HEAD, it says preflight OPTIONS failed due to CORS policy of Access-Control-Allow-Origin being unset. Even more weird, when sending a OPTIONS request, the first fails but the second succeeds with the options request correctly displaying the OPTIONS response Access-Control-Allow-Origin. – Rahmi Pruitt Oct 19 '20 at 03:02

1 Answers1

0

Apparently, in order to do a plain OPTIONS request, the server must set header Access-Control-Allow-Methods with OPTIONS. It does not matter when a GET request sends a preflight OPTIONS.

In case you would like to see the coded solution below https://github.com/syncthing/syncthing/blob/1d3b9876f6f7a4ece0ca31a5abbab45a38aa7d57/lib/api/api.go#L514.

Rahmi Pruitt
  • 569
  • 1
  • 8
  • 28