2021年6月17日 星期四

[ionic, native, cordova, http] How to use cordova-plugin-advanced-http module to post/get resource (CORS issue)

How to use cordova-plugin- advanced-http module to post/get data

井民全, Jing, mqjing@gmail.com


Quick

public async testCordovaHTTP_get(){

    console.log('testCordovaHTTP_get')

    const url = 'http://www.google.com';

    this.http.get(url, {}, {}).then(response => {

      alert('response.status = ' + response.status);

      alert('response.data = ' + response.data); // data received by server

      alert('response.headers = ' + response.headers);

    })

    .catch(error => {

      alert('error.status = ' + error.status);

      alert('error.error = ' + error.error); // error message as string

      alert('error.headers = ' + error.headers);

  

    });

  }



Table of Contents

1. The CORS issue

2. Supports

3. Create the basic app frameworks

3.1. Ionic App Skeleon

3.2. Android platform

4. Code

4.1. Step 1: Install package

4.2. Step 2: Declare the plugin

4.3. Step 3: Method: POST

4.4. Run

5. Method: Get

6. References

7. Trobuleshooting

7.1. Q: How to resolve the cross-domain request?

7.2. Q: How to use Cordova or Capacitor to build native mobile apps

7.3. Q: Cordova is not available. Make sure to include cordova.js or run in a device/simulator


1. The CORS issue


You can use Fetch or XMLHttpRequest to fetching resources from the endpoint API on a local/remote server. However, if the endpoint API on the remote site does not enable cors, you will get this.

Access to fetch at 'http://192.168.21.14:9000/statusAPI' from origin 'http://localhost:8100' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.


From the doc, this is because the origin is different from the resource URL that you just requested. Your browser blocked the request for the security issue. If you can enable the cors by adding the following code that marked as blue on the remote resource holder, then you can freely use Fetch to access the resource without cors issues.

Here  are more options can be used, if you controlled the resource holder.

File: server/routes/statusAPI.ts

router.get('/', function(req:Request, res:Response, next) {

    console.log(JSON.stringify(req.headers));  // print request headers for checking 

    res.header("Access-Control-Allow-Origin", "*"); // Allow any origin server to request resource

    res.send('The statusAPI was invoked.');

});


module.exports = router;


However, we cannot touch the 3-party resource holders. Try to access 'www.google.com'! The real problem is HOW TO GET the RESOURCE from the 3-PARTY RESOURCE HOLDER. You can use the Cordova native HTTP plugin to do this for you. The implementation does not apply the CORS restrictions.



Further information about the cors, you can check the document Cross-Origin Resource Sharing (CORS), https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


If you are interested in other solutions for the cors issue. IONIC has a good document " CORS Errors", https://ionicframework.com/docs/troubleshooting/cors#2-native-pwas
It mentioned the solutions including 

  1. using native plugin (this document),

  2. setup a proxy in the middle

  3. enable the cors if you control the resource holder,

  4. Disable the cors/ --disable-web-security

You can check it.

   

Here, I will show you how to use cordova-plugin-advanced-http to get access remote resources with no cors enabled API.

2. Supports

  • iOS and Android  (no browser)

3. Create the basic app frameworks

3.1. Ionic App Skeleon

ionic start myApp tabs


Step 1: Create a service class for encapsulating the native methods

Command:

ionic g service services/myService

output:

CREATE src/app/services/my-service.service.spec.ts 

CREATE src/app/services/my-service.service.ts (138 bytes)


3.2. Android platform

ionic cordova prepare android  # {android/ios}

ionic cordova run android --host 192.168.21.3    # test run on a Android hardware


Debug

Open Chrome browser

chrome://inspect


4. Code

4.1. Step 1: Install package

ionic cordova plugin add cordova-plugin-advanced-http

 npm install @ionic-native/http



4.2. Step 2: Declare the plugin

File: myApp/src/app/app.module.ts

import { HTTP } from '@ionic-native/http/ngx';


@NgModule({

          ...

          providers: [..., HTTP],

          ...

      })



4.3. Step 3: Method: POST

import { HTTP } from '@ionic-native/http/ngx'


export class MyServiceService {

    constructor(public http:HTTP){

   }


    public async public sendLineMessage(urlEndPoint:string, strMsg:string, strToken:string){

    var data = {

      message: 'send from ionic angular android',

      // imageFile: bufContent

    }

    

 

    var options = {

        //multipart: true,    // must have for sending image.

        //json: true,

        headers: { 'Authorization': 'Bearer eBTHTlHvJJXX8Bc6WsQ8XPs05j75Vbz4rj7FNgrivVj' }

    }


    // debugger;


    this.http.post(urlEndPoint, data, options.headers).then(data => {

      console.log(data.status);

      console.log(data.data); // data received by server

      console.log(data.headers);

  

    })

    .catch(error => {

  

      console.log(error.status);

      console.log(error.error); // error message as string

      console.log(error.headers);

  

    });

  }

}


4.4. Run

ionic cordova run android --host 192.168.21.3    # test run


Debug

Open Chrome browser

chrome://inspect


5. Method: Get

public async testCordovaHTTP_get(){

    console.log('testCordovaHTTP_get')

    const url = 'http://192.168.21.14:9000/statusAPI'; 

    // const url = 'http://www.google.com';

    this.http.get(url, {}, {}).then(response => {

      alert('response.status = ' + response.status);

      alert('response.data = ' + response.data); // data received by server

      alert('response.headers = ' + response.headers);

    })

    .catch(error => {

      alert('error.status = ' + error.status);

      alert('error.error = ' + error.error); // error message as string

      alert('error.headers = ' + error.headers);

  

    });

  }




6. References

  1. https://ionicframework.com/docs/troubleshooting/cors#2-native-pwas

  2. https://ionicframework.com/docs/v3/native/http/

  3. https://ionicframework.com/docs/native/community

  4. https://bobcares.com/blog/how-to-post-and-get-data-with-native-http-plugin/

7. Trobuleshooting

7.1. Q: How to resolve the cross-domain request?

 

 => Use cordova plug-ins, this document.

 

Step 1: install packages

 ionic cordova plugin add cordova-plugin-advanced-http

 npm install @ionic-native/http


Step 2: Register Providers

  File: app.module.ts

  (a) import to @NgModule 

      import { HTTP } from '@ionic-native/http/ngx'; 

      

  (b) Add to Providers

      @NgModule({

          ...

          providers: [..., HTTP],

          ...

      })

      

  (c) In your services

      import { HTTP } from '@ionic-native/http/ngx';

      

    ...

       

       var data = {

      message: 'send from ionic angular android',

      // imageFile: bufContent

    }

    

 

    var options = {

        //multipart: true,    // must have for sending image.

        //json: true,

        headers: { 'Authorization': 'Bearer eBTHTlHvJJXX8Bc6WsQ8XPs05j75Vbz4rj7FNgrivVj' }

    }


    // debugger;


    this.http.post(urlEndPoint, data, options.headers).then(data => {

      console.log(data.status);

      console.log(data.data); // data received by server

      console.log(data.headers);

  

    })

    .catch(error => {

  

      console.log(error.status);

      console.log(error.error); // error message as string

      console.log(error.headers);

  

    });

 

 

 





7.2. Q: How to use Cordova or Capacitor to build native mobile apps 

=>

 import the plugin in a @NgModule and add it to the list of Providers

 

 Reference

 https://ionicframework.com/docs/native/community



7.3. Q: Cordova is not available. Make sure to include cordova.js or run in a device/simulator

=>

 Step 1: ionic cordova prepare {browser/android/ios}

 Step 2: ionic cordova run  {browser/android/ios} -l  

        ionic cordova run browser 

 

 https://stackoverflow.com/questions/55965710/ionic-4-cordova-is-not-available-make-sure-to-include-cordova-js-or-run-in-a-d/55966171