cordova-plugin-advanced-http icon indicating copy to clipboard operation
cordova-plugin-advanced-http copied to clipboard

[Bug] Android Http setHeaders ignored in code

Open rickblommetjes opened this issue 2 years ago • 3 comments

We are suffering issues connecting with the http client to an External API (from Microsoft) where after an upgrade at their side we don't receive any response from the api, it has something to do with the headers send to the API since it works with Postman, curl and IOS. When sending from Android the setHEader which are require seems to be ignored by the plugin, or did we missed something else? The Bearer Token is added, the rest is ignored.

Ioniv V5 "dependencies": { "@angular/common": "~12.1.1", "@angular/core": "~12.1.1", "@angular/forms": "~12.1.1", "@angular/platform-browser": "~12.1.1", "@angular/platform-browser-dynamic": "~12.1.1", "@angular/router": "~12.1.1", "@ionic-native/app-version": "^5.36.0", "@ionic-native/barcode-scanner": "^5.33.0", "@ionic-native/core": "^5.33.1", "@ionic-native/device": "^5.33.0", "@ionic-native/file": "^5.36.0", "@ionic-native/http": "^5.33.0", "@ionic-native/in-app-browser": "^5.33.1", "@ionic/angular": "^5.5.2", "@ionic/storage-angular": "^3.0.6", "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", "com-darryncampbell-cordova-plugin-intent": "^1.3.0", "cordova-android": "^7.1.4", "cordova-ios": "~4.5.4", "cordova-plugin-advanced-http": "^3.2.2", "cordova-plugin-app-version": "^0.1.12", "cordova-plugin-console": "^1.1.0", "cordova-plugin-device": "^2.0.2", "cordova-plugin-file": "^6.0.2", "cordova-plugin-inappbrowser": "^4.1.0", "cordova-plugin-ionic-keyboard": "^2.2.0", "cordova-plugin-ionic-webview": "^4.2.1", "cordova-plugin-splashscreen": "^5.0.2", "cordova-plugin-statusbar": "^2.4.2", "cordova-plugin-whitelist": "^1.3.3", "cordova-sqlite-storage": "^6.0.0", "localforage": "^1.10.0", "localforage-cordovasqlitedriver": "^1.8.0", "ngforage": "^6.0.0", "phonegap-plugin-barcodescanner": "^8.1.0", "rxjs": "~6.6.0", "rxjs-compat": "^6.6.7", "tslib": "^2.2.0", "zone.js": "~0.11.4" },

Typescript code:

 public async get(cmd: string, retryCount: number = maxRetries) {
        // don"t have the data yet
        const token = await this.localData.getToken();
        this.userlist = await this.localData.getUserList();
        const user: UserService = await this.localData.getCurrentUser();
        return new Promise(async (resolve) => {
            // We"re using Angular Http provider to request the data,
            // then on the response it"ll map the JSON data to a parsed JS object.
            // Next we process the data and resolve the promise with the new data.
            // this.authHttp.get(this.baseURL + cmd).subscribe(
            if (!user) {
                resolve({ error: true, msg: 'Not logged in' });
            }
            this.httpProd.setHeader("*", "Authorization", "Bearer " + token);
            this.httpProd.setHeader("*", "application/json;charset=utf-8", "gzip");
            this.httpProd.setHeader("*", "Accept-Encoding", "gzip");
            this.httpProd.get(this.getUrl(user, cmd), {}, {})
                .then(
                    (data: any) => {
                        return resolve(JSON.parse(data.data));
                    })
                .catch(async (err) => {
                    if (err && err.status && (err.status == 401 || err.status == 500) && user && user.refreshToken) {
                        await this.useRefreshToken(user);
                        const token = await this.localData.getToken();
                        this.httpProd.setHeader("*", "Authorization", "Bearer " + token);
                        this.httpProd.setHeader("*", "application/json;charset=utf-8", "gzip");
                        this.httpProd.setHeader("*", "Accept-Encoding", "gzip");
                        this.httpProd.get(this.getUrl(user, cmd), {}, {})
                            .then(
                                (data: any) => {
                                    return resolve(JSON.parse(data.data));
                                })
                            .catch(async (err) => {
                                this.showError(err, resolve);
                            });
                    } else {
                        if (err && err.status < 0 && retryCount > 0) {
                            const loading = await this.loadingCtrl.create({
                                message: "Connection problems. Retry " + (maxRetries + 1 - retryCount) + "...",
                            });
                            loading.present();
                            return this.sleep(10000).then(async () => {
                                const data = await this.get(cmd, retryCount - 1);
                                loading.dismiss();
                                resolve(data);
                            })
                        }
                        this.showError(err, resolve);
                    }
                });
        });
    }

Result in Telemetry on the external api:

{"Accept-Charset":["UTF-8"],"Accept-Encoding":["gzip"],"Authorization":["Bearer "],"Connection":["Keep-Alive"],"User-Agent":["Dalvik/2.1.0 (Linux; U; Android 11; SM-A202F Build/RP1A.200720.012)"],"client-request-id":["569b240c-a132-4c47-b143-349a84669d8e"],"request-id":["2268f33f-eedd-4c96-a8a2-7d05a7e3926b"]}     working Curl Command

curl -H "Content-Type: application/json;charset=utf-8" -H "User-Agent: Dalvik/2.1.0 (Linux; U; Android 11; SM-A202F Build/RP1A.200720.012)" -H "Accept-Charset: UTF-8" -H "Accept-Encoding: gzip" -H "Connection: Keep-Alive" -H "Authorization: Bearer https://api.businesscentral.dynamics.com/v2.0/<tenantId>/Sandbox/api/v2.0/companies

rickblommetjes avatar May 11 '22 14:05 rickblommetjes

This is just a dumb guess but have you tried setting the headers like this: headers: { "Content-Type": "application/json" , [...] } for the request? My headers aren't ignored and I am doing it like that.

ZweiEuro avatar Jun 19 '22 14:06 ZweiEuro

@rickblommetjes I've updated your text to make the code sample easier to read. And I agree with @ZweiEuro. You are providing application/json;charset=utf-8" as a key and gzip as the corresponding value. This is definitely wrong, because this is not a valid HTTP header key.

silkimen avatar Sep 16 '22 03:09 silkimen

ok I have a look at it thnx, in the mean time a hotfix has been applied by Microsoft to solve the issue, but clean coding is always better:-)

rickblommetjes avatar Sep 17 '22 11:09 rickblommetjes