I have an Android app and a Flutter-web app that fetch some files from my github pages site.
The following command
.\curl -v https://mygithubaccount.github.io/myrepository/config.yaml > log_command.txt
confirms that the github.io server allows all origins for what concerns the CORS policies. Indeed the output includes these lines:
< server: GitHub.com
< content-type: text/yaml
< permissions-policy: interest-cohort=()
< last-modified: Thu, 06 Jun 2024 10:05:37 GMT
< access-control-allow-origin: *
Instead, as it seems, both the Android WebView and the browser send a preflight request that fails. The present question is about how to circumvent this behaviour.
If the web security option is enforced I get this kind of errors:
Access to XMLHttpRequest at 'https://mygithubaccount.github.io/myrepository/config.yaml' from origin 'http://localhost:63988' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In the Android app, the request is performed inside the WebView by means of Javascript code like
response = await fetch(urlString, {
headers: { 'method': 'GET','Content-Type': 'application/yaml' },
});
It is surrounded by try catch, and the error is simply
TypeError fetch: Failed to fetch
In debug mode I see the headers of the request:
"Origin" -> "https://www.myapp.info"
"Accept" -> "*/*"
"Access-Control-Request-Method" -> "GET"
"Access-Control-Request-Headers" -> "content-type,method"
"User-Agent" -> "Mozilla/5.0 (Linux; Android 11; SM-A105FN Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.179 Mobile Safari/537.36 myapp_app_mobile_android"
"Referer" -> "https://www.myapp.info/"
"Sec-Fetch-Mode" -> "cors"
The Android code include setting the CORS mode as below
cacheWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
and intercepting the OPTIONS request with "Access-Control-Request-Method" in the headers to provide a response that possibily leads to fetch success instead of fail.
cacheWebView.setWebViewClient(new WebViewClient(){
@Override
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
Map<String,String> headers=request.getRequestHeaders();
// Check if the request is a preflight request (OPTIONS method)
if (headers.get("Access-Control-Request-Method") != null) {
// Create a custom response to skip the preflight request
InputStream emptyStream = new ByteArrayInputStream(new byte[0]);
headers.put("Access-Control-Allow-Origin","*");
headers.put("Access-Control-Allow-Methods", "GET, HEAD");
headers.put("Access-Control-Allow-Headers", "Content-Type, Authorization");
headers.put("Access-Control-Max-Age", "3600");
return new WebResourceResponse("text/plain", "UTF-8",200,"ok",headers, emptyStream);
}
// Allow other requests to proceed as normal
return super.shouldInterceptRequest(view, request);
}
But the error is still issued, I cannot create or pass a good response so that my Android app continues fetching the actual content. My goal is fixing this issue both for the Android and the Flutter-web apps.
content-type
request header - you're not SENDING yaml in a GET are you!! That may well prevent the pre-flight from occurring