I am having immense difficulty figuring out how to set a request timeout using the Windows.Web.HttpClient made available through WinRT. The application I am working on is a JavaScript-type Universal Windows app. "client-side", the JavaScript has access to use a variety of namespaces that one would normally utilize if programming in C#. Members of these namespaces can be accessed off the window object like so:
const {
HttpRequestMessage,
HttpMethod,
HttpClient,
} = R.pathOr({}, ['Windows', 'Web', 'Http'], window);
The goal of the code I will post below is to do a simple reach-ability check on a URL before the app redirects there, and in case someone wonders why I have not just done so using the more standard means in JavaScript (ex: XMLHttpRequest), it is because CORS sometimes fails those requests. Since I work for a large company, it is neither easy to request the proper access-control-allow-origin headers be added everywhere, and besides that, we have testers that are side-loading onto devices, running proxies, etc...
That said, although I was able to locate documentation with some relevance for the task at hand, the examples are all in C# and I have noticed that not everything on the JavaScript side of things aligns perfectly with this documentation.
A Stack Overflow user asked a very similar question here and the accepted solution was to use CancellationTokenSource. However, so far as I know, the C# solution to this problem does not apply to the JavaScript side of things, but I did come up with a near-solution where I am able to cancel the task using setTimeout. Please note that I have edited out some lines of code here for readability.
const isReachable = async (url) => (
new Promise((resolve) => {
const message = new HttpRequestMessage();
message.method = new HttpMethod('HEAD');
message.requestUri = new Uri(url);
const client = new HttpClient();
const task = client.sendRequestAsync(message);
const timeout = setTimeout(() => task.cancel(), 5000);
task.done(
(result) => { // Success
clearTimeout(timeout);
resolve(true);
},
(result) => { // Failure
clearTimeout(timeout);
resolve(false);
},
);
})
);
The above code seemed to work well on it's own, but then I noticed that the arguments being passed into the callback functions (arg named response) were not what I expected. I expected something at least similar to an XHR response, but what I get instead seems to be either a success or error response for the task. The problem is, I do need to get the status code and failure reason so to log it for our reports (that code is not illustrated).
This was my next (partial) attempt and apparently, if I await the response, then I actually do get an object similar enough to an XHR response to be used for that purpose. However, since I am awaiting the task here, I'm not storing it in a variable so that it can be canceled after my timing out.
const urlIsReachable = async (url = '') => (
new Promise(async (resolve) => {
const request = new HttpRequestMessage();
request.method = new HttpMethod('HEAD');
request.requestUri = new Uri(url);
const client = new HttpClient();
const response = await client.sendRequestAsync(request);
const { statusCode: status } = response;
if (status === 200) {
resolve(true);
return;
}
resolve(false);
})
);
In conclusion, I didn't think something as simple as setting a timeout threshold would be such a pain, but I have not been able to locate a way to do so.