Switching from UIWebView to WKWebView is great, but as it performs stricter CORS checks than standard Cordova/Phonegap it can seem at first that remote API calls are broken in your app.
Basically, before WKWebView does any AJAX request, it first sends a HTTP OPTIONS
query and looks at the Access-Control-*
headers that are returned to determine if it is able to access the service. Most browsers can be made to allow all AJAX requests via a simple “Access-Control-Allow-Origin: *
” header, however WKWebView is more picky. It requires that you expose which methods (GET, POST, etc); and which headers are allowed (eg if you are using JSON AJAX requests you probably need to use a “Content-Type: application/json
” header in your main request).
Rather than having to update your API service, you can work around this in a general way using the following Apache config:
# Required configuration for iOS WkWEBVIEW # Allow any location to access this service Header always set Access-Control-Allow-Origin "*" # Allow the following headers in requests (X-Auth is a custom header, also allow Content-Type to be specified) Header always set Access-Control-Allow-Headers "X-Auth, content-type, origin" Header always set Access-Control-Expose-Headers "X-Auth" # Allow the following methods to be used Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS" # WkWebView sends OPTIONS requests to get CORS details. Don't tie up the API service with them; # just answer them via apache itself RewriteEngine On RewriteCond %{REQUEST_METHOD} =OPTIONS RewriteRule .* - [R=204,END]
Note the last line answers any HTTP OPTIONS
request with blank content and returns it straight away. Most API services would cause a lot of CPU processing just to handle a single request whether it is a true request or an OPTIONS query, so we just answer this straight from Apache without bothering to send it through to the API. The R=204
is a trick to specify that we don’t return any content (HTTP 204 code means “Success, but no content”). Otherwise if we used something like R=200
it would return a page talking about internal server error, but with a 200 response which is more bandwidth, more processing and more confusing for any users.