Error on http requests from ionic iOS native to WP rest API (works on web view and DevApp)

mik*_*lin 4 cordova ionic-framework wordpress-rest-api

We are trying to issue http requests from our ionic app to a Wordpress server (REST API) and get the following error: {"_body":{"isTrusted":true},"status":0,"ok":false,"statusText":"","headers":{},"type":3,"url":null}.

The requests are working fine when we use the web view or ionic DevApp and are failing on iOS devices.

What we did so far:

  • We verified the requests work fine through the DevApp and the web view.
  • We relaxed the cordova whitelist plugin (see our config.xml below).
  • We verified CORS are enabled on our servers (see curl CORS check below)
  • We checked there is no CORS preflight request issued from the iOS device when the request is blocked as we can see the GET request and no OPTIONS request on the server access log.
  • Obviously there is connectivity from the device to the server as we can see the GET request.

If you have any suggestions, even if seem far fetched, we would very much like to hear them.

Thanks for the help!

请求代码

import { Http, Response } from '@angular/http';

...

private requestData(path: String, params:Object = {}){
  return this.http.get( this.request.url + path, {
    params: {
      'consumer_key': this.conf.comm.appId,
      'consumer_secret': this.conf.comm.appSecret
    }
  })
  .map( (res: Response) => this.prepareResponse(res) )
  .catch( (res: Response) => this.catchError(res) );
}
Run Code Online (Sandbox Code Playgroud)

配置文件

<?xml version='1.0' encoding='utf-8'?>
<widget id="app.c***r.***" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>***</name>
    <description>The ***</description>
    <author email="admin@c***r.app" href="https://c***r.app">***</author>
    <content src="index.html" />
    <access origin="*" />
    <access origin="*" subdomains="true" />
    <allow-navigation href="http://*/*" />
    <allow-navigation href="https://*/*" />
    <allow-navigation href="localhost:8080" />
    <allow-navigation href="data:*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="mailto:*" />
    <preference name="ScrollEnabled" value="false" />
    <preference name="android-minSdkVersion" value="19" />
    <preference name="BackupWebStorage" value="none" />
    <preference name="SplashMaintainAspectRatio" value="true" />
    <preference name="FadeSplashScreenDuration" value="300" />
    <preference name="SplashShowOnlyFirstTime" value="false" />
    <preference name="SplashScreen" value="screen" />
    <preference name="SplashScreenDelay" value="3000" />
    <platform name="android">
        <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
        ...
        <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
    </platform>
    <platform name="ios">
        <icon height="57" src="resources/ios/icon/icon.png" width="57" />
        ...
        <splash height="2732" src="resources/ios/splash/Default@2x~universal~anyany.png" width="2732" />
    </platform>
    <plugin name="cordova-plugin-whitelist" spec="1.3.3" />
    <plugin name="cordova-plugin-statusbar" spec="2.4.2" />
    <plugin name="cordova-plugin-device" spec="2.0.2" />
    <plugin name="cordova-plugin-splashscreen" spec="5.0.2" />
    <plugin name="cordova-plugin-ionic-webview" spec="^3.0.0" />
    <plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" />
    <plugin name="cordova-sqlite-storage" spec="3.2.0" />
    <engine name="ios" spec="~4.5.5" />
    <engine name="android" spec="~7.1.4" />
</widget>
Run Code Online (Sandbox Code Playgroud)

卷曲 CORS 检查

* Hostname was NOT found in DNS cache
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 18.224.***.***...
* Connected to p***r.app (18.224.***.***) port 443 (#0)
* successfully set certificate verify locations:
...
*        SSL certificate verify ok.
> GET /wp-json/wc/v2/products/categories?consumer_key=ck_3***2&consumer_secret=cs_0***b&per_page=100 HTTP/1.1
> User-Agent: curl/7.38.0
> Host: p***r.app
> Accept: */*
> Origin: http://localhost:8080
>
< HTTP/1.1 200 OK
< Date: Fri, 12 Apr 2019 14:44:43 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-Powered-By: PHP/7.0.31
< X-Robots-Tag: noindex
< Link: <https://p***r.app/wp-json/>; rel="https://api.w.org/"
< X-Content-Type-Options: nosniff
< Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
< Access-Control-Allow-Headers: Authorization, Content-Type
< X-WP-Total: 98
< X-WP-TotalPages: 1
< Cache-Control: public, max-age=2592000
< Allow: GET
< Access-Control-Allow-Origin: http://localhost:8080
< Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE
< Access-Control-Allow-Credentials: true
< Vary: Origin
< X-Frame-Options: SAMEORIGIN
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=UTF-8
<
Run Code Online (Sandbox Code Playgroud)

mik*_*lin 8

该问题是由ionic://localhost作为编译应用程序使用时作为源的离子发送引起的。WP REST 通过rest_send_cors_headers 进行响应,它通过原点esc_url_raw并根据其协议拒绝该 url。

要解决这个问题,只需ionic通过过滤器将协议添加到允许的协议列表中kses_allowed_protocols

顺便说一句,如果您来自 ionic 并且正在阅读本文,请考虑使已编译的应用程序的行为尽可能接近 Web 视图和 DevApp,包括发送到服务器的源。


小智 7

这是我在看到上面有用的答案后使用的代码。发布以防其他人正在寻找相同的解决方案。这可以放在您的主题中的functions.php 中或任何方便的地方。

add_filter('kses_allowed_protocols', function($protocols) {
    $protocols[] = 'ionic';
    return $protocols;
});
Run Code Online (Sandbox Code Playgroud)