1

I'm trying to host on a server an Ionic 3 app. The app is correctly working on iOS, Android, and on localhost (ionic serve) but it doesn't work once hosted and I'm going crazy to solve the issue because there are no errors!

The Server is a Digital Ocean droplet. On it, I have mounted a Docker-compose environment because I need to put multiple RestAPI+frontend on the same machine.

Right now on docker-compose, there are the following relevant services (+other not useful for the problem):

  • Nginx proxy for ELK stack: only care about the particular port and ask for user and password before redirecting on Kibana [WORKS as expected];
  • Nginx auto-reverseproxy for new containers: each new (frontend) container will be proxied behind a subdomain [WORKS as expected];
  • ExpressJS RestAPI (non-proxied): already taken care about CORS and other minor issues [WORKS as expected];
  • Ionic frontend container: the problematic one!

The problem seems to be that the Ionic container can not receive all the headers of an API request. During login request the server sends me back an Authorization and a refreshToken header and I need them for the further request!

I'll attach some images to better explain what I mean:

EXPECTED BEHAVIOUR (happens on localhost)

XHR POST from Chrome:

enter image description here

Console Log from Ionic:

enter image description here

STRANGE BEHAVIOUR (happens on hosted ionic)

XHR (preamble request):

enter image description here

XHR POST from Chrome:

enter image description here

Console Log from hosted-Ionic:

enter image description here

Why the console.log from hosted-ionic don't receive/show the headers I want?

IONIC CODE of the request (function -> to request)

  • login.ts

    local_login(){
        console.log('dati inviati = user: ',this.user);
    
        this.req.local_login(this.user).then(data => {
          this.spinnerDialog.hide();
          if(data['status'] == 200){
            console.log('Ok => HomePage')
            this.goToPage("HomePage")
          }
          else {
            console.log('Login fallito => LoginPage')
            this.goToPage("LoginPage")
          }
        });
    
      }
    
  • request.ts

    local_login(body) {
        return new Promise(resolve => {
            let headers = new Headers();
            headers.append('Content-Type', 'application/json');
            headers.append('Authorization', this.commonVar.jwt);// EMPTY var
            headers.append('refreshToken', this.commonVar.rjwt);// EMPTY var
            this.http.post(this.site+':'+this.port+'/api/'+this._v+'/auth/local/login', body, {headers: headers})
            .subscribe((data) => {
              console.log('data >>>',data);
    
              data['_body'] = JSON.parse(data['_body']);
              if(data['status'] === 200){
                this.commonVar.jwt = data.headers.get('Authorization');
                console.log('Local >>>',data.headers.get('Authorization'))
                console.log('Storage >>>',this.commonVar.jwt)
    
                this.commonVar.rjwt = data.headers.get('refreshToken');
                console.log('Local >>>',data.headers.get('refreshToken'))
                console.log('Storage >>>',this.commonVar.rjwt)
    
                this.commonVar.user = JSON.stringify(data['_body']['data']);
                console.log('USER by Login =>',this.commonVar.user);
                console.log('login OK');
              }
              else {
                //TODO: handling error login
              }
              resolve(data);
            },error => {
              //TODO: handling error login
              console.error(error);
            });
        });
      }
    

As you can see the console log of data (the response) is complete only on the localhost. But from chrome xhr i can see all the headers. Also, the console log of a single header doesn't work (null).

It seems like the code doesn't wait before the console.log but this is not possible. I tried also the promise form of the HTTP module with no luck.

Maybe the problem is related to Docker?

I tried to execute the Ionic container in these ways:

  • serving the www folder through both dedicated or shared nginx instance.
  • serving the platform/browser/www same way as above.
  • executing ionic serve with various flag combination.

All these ways reproduce the same problem.

Initially, I was using localStorage through indexedDB and I thought it was the problem. So I also tried to remove it (as you can see how I use shared vars) but the problem is still there.

If I forgot something please ask.

Thanks to anyone can point me in the right direction!

Tomislav Stankovic
  • 3,080
  • 17
  • 35
  • 42

1 Answers1

1

Thanks to this answer I was pointed in the right direction.

The problem wasn't ionic by itself, instead it was about the Rest server's CORS configuration. I configured everything I needed about headers for incoming connection but I forgot to configure it for outgoing ones.

Just in case someone will have the same problem:

This was my previous configuration on ExpressJS about CORS:

const express = require('express');
var app = express();

[...]

var allowCrossDomain = function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization,refreshToken');
  next();
};

[...]

app.use(allowCrossDomain);

And after the correction:

const express = require('express');
var app = express();

[...]

var allowCrossDomain = function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization,refreshToken');
  res.header('Access-Control-Expose-Headers', 'Content-Type,Authorization,refreshToken');
  /* ^^^ This was the needed line! ^^^         ^^^ here you put your custom headers ^^^ */
  next();
};

[...]

app.use(allowCrossDomain);

Hope this can help someone else