Issues making https calls in ios

Hello !
Thanks to Ionic, I have an Android App that makes successful API calls to a remote server I own. Thank you Ionic!

However, I recently tried building for ios and I’m running into an issue.

I use CapacitorHttp (import from capacitor/core) to make the API calls within my code.
It works fine in Android but not in IOs.

I wish I could paste some errors from the console but that’s my issue: nothing happens when the API call is made.
No feedback or error from Xcode, just… no behavior at all.
I tried logging the CapacitorHttp object and the method call “CapacitorHttp.post(options);”
but nothing comes up in the Xcode console, just “{}”.

I’m thinking I miss some configuration but I can’t find what.

Here is my config:

Ionic:

Ionic CLI : 7.1.1 (/opt/homebrew/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/vue 6.3.8

Capacitor:

Capacitor CLI : 4.5.0
@capacitor/android : 4.5.0
@capacitor/core : 4.5.0
@capacitor/ios : 4.5.0

Utility:

cordova-res : not installed globally
native-run (update available: 2.0.0) : 1.7.1

System:

NodeJS : v21.1.0 (/opt/homebrew/Cellar/node/21.1.0/bin/node)
npm : 10.2.3
OS : macOS Unknown
Capacitor config: import { CapacitorConfig } from ‘@capacitor/cli’;

const config: CapacitorConfig = {
appId: 'eu…,
appName: 'my app name,
webDir: ‘dist’,
bundledWebRuntime: false,
server: { “androidScheme”: “http”, “allowNavigation”: [ “127.0.0.1” ] },
plugins: {
CapacitorHttp: {
enabled: true,
},
},
ios:{
includePlugins: [ “CapacitorHttp” ]
}
};

export default config; ionic.config:
{
“name”: “intercambio”,
“integrations”: {
“capacitor”: {}
},
“type”: “vue”
}

Package: {
“name”: “intercambio”,
“version”: “0.0.1”,
“private”: true,
“scripts”: {
“serve”: “vue-cli-service serve”,
“build”: “vue-cli-service build”,
“test:unit”: “vue-cli-service test:unit”,
“test:e2e”: “vue-cli-service test:e2e”,
“lint”: “vue-cli-service lint”
},
“dependencies”: {
@awesome-cordova-plugins/http”: “^6.4.0”,
@capacitor/android”: “4.5.0”,
@capacitor/app”: “4.1.1”,
@capacitor/camera”: “^4.1.4”,
@capacitor/core”: “4.5.0”,
@capacitor/device”: “^4.1.0”,
@capacitor/haptics”: “4.1.0”,
@capacitor/ios”: “4.5.0”,
@capacitor/keyboard”: “4.1.0”,
@capacitor/preferences”: “^4.0.2”,
@capacitor/status-bar”: “4.1.0”,
@ionic-native/http”: “^5.36.0”,
@ionic/vue”: “^6.0.0”,
@ionic/vue-router”: “^6.0.0”,
“axios”: “^1.2.3”,
“cordova-plugin-advanced-http”: “^3.3.1”,
“core-js”: “^3.6.5”,
“ionicons”: “^6.0.3”,
“vue”: “^3.2.21”,
“vue-i18n”: “^9.2.2”,
“vue-router”: “^4.0.12”,
“vuex”: “^4.1.0”
},
“devDependencies”: {
@capacitor/cli”: “4.5.0”,
@types/jest”: “^27.0.2”,
@typescript-eslint/eslint-plugin”: “^5.6.0”,
@typescript-eslint/parser”: “^5.6.0”,
@vue/cli-plugin-babel”: “~5.0.0-rc.1”,
@vue/cli-plugin-e2e-cypress”: “~5.0.0-rc.1”,
@vue/cli-plugin-eslint”: “~5.0.0-rc.1”,
@vue/cli-plugin-router”: “~5.0.0-rc.1”,
@vue/cli-plugin-typescript”: “~5.0.0-rc.1”,
@vue/cli-plugin-unit-jest”: “~5.0.0-rc.1”,
@vue/cli-service”: “~5.0.0-rc.1”,
@vue/eslint-config-typescript”: “^9.1.0”,
@vue/test-utils”: “^2.0.0-rc.16”,
@vue/vue3-jest”: “^27.0.0-alpha.3”,
“babel-jest”: “^27.3.1”,
“cypress”: “^8.7.0”,
“eslint”: “^8.4.1”,
“eslint-plugin-vue”: “^8.2.0”,
“jest”: “^27.3.1”,
“ts-jest”: “^27.0.7”,
“typescript”: “^4.3.5”
},
“description”: “An Ionic project”
}

<?xml version="1.0" encoding="UTF-8"?> CFBundleDevelopmentRegion en CFBundleDisplayName Intercambio plus app CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance

Please use proper code blocks to make it easier for us to read :slight_smile:

Capacitor 4.5.0 was released a year ago. The current version is 5.5.1 and many improvements have been made to the HTTP plugin. So, I would first upgrade to Capacitor 5.

I also see that you have @awesome-cordova-plugins/http and @ionic-native/http installed but you say you are using the 1st party HTTP plugin built into Capacitor so I would uninstall those two plugins. awesome-cordova-plugins also replaced ionic-native - see A New Chapter for @ionic-native - Ionic Blog.

1 Like

Sorry for the format!
Thanks for your answer I’ll try this :slight_smile:

1 Like

I updated capacitor and pruned all unused packages, but I still have the issue :confused:

Seems like CapacitorHttp is empty, cannot log the object, still gives me a “{}” in xcode console.

I put the api call within a try/catch and try to log both the response boject (async) and the potential error, but nothing, I’m in the dark.

I get a message in the debugger though, that looks like totally irrelevant:

Nov  9 18:07:31 MacBook-Pro-de-YuzuPulse syslogd[49446]: Configuration Notice:
ASL Module "com.apple.contacts.ContactsAutocomplete" claims selected messages.
Those messages may not appear in standard system log files or in the ASL database.

-[RTIInputSystemClient remoteTextInputSessionWithID:textSuggestionsChanged:]  Can only set suggestions for an active session. sessionID = 07680F0E-53CE-4DD1-A981-C3087A1285D6

Unable to simultaneously satisfy constraints.

	Probably at least one of the constraints in the following list is one you don't want. 

	Try this: 

		(1) look at each constraint and try to figure out which you don't expect; 

		(2) find the code that added the unwanted constraint or constraints and fix it. 

(

    "<NSLayoutConstraint:0x60000214dbd0 'accessoryView.bottom' _UIRemoteKeyboardPlaceholderView:0x105837190.bottom == _UIKBCompatInputView:0x10580ce90.top   (active)>",

    "<NSLayoutConstraint:0x60000212b4d0 'assistantHeight' SystemInputAssistantView.height == 45   (active, names: SystemInputAssistantView:0x105819730 )>",

    "<NSLayoutConstraint:0x6000021499a0 'assistantView.bottom' SystemInputAssistantView.bottom == _UIKBCompatInputView:0x10580ce90.top   (active, names: SystemInputAssistantView:0x105819730 )>",

    "<NSLayoutConstraint:0x60000214c690 'assistantView.top' V:[_UIRemoteKeyboardPlaceholderView:0x105837190]-(0)-[SystemInputAssistantView]   (active, names: SystemInputAssistantView:0x105819730 )>"

)


Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x60000214c690 'assistantView.top' V:[_UIRemoteKeyboardPlaceholderView:0x105837190]-(0)-[SystemInputAssistantView]   (active, names: SystemInputAssistantView:0x105819730 )>


Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

Try removing the above from your Capacitor config in the iOS section. Otherwise, I think you’ll need to share your updated packages and the code that you are using to make the HTTP calls.

Thanks again for the time you invest in helping me :slight_smile:

Here are excerpt from the code:

import { Preferences } from '@capacitor/preferences';
import { CapacitorHttp } from '@capacitor/core';


const urlbase = "https://staging2.intercambioplus.eu/";

...

const actions = {
    async loginUser({ commit }: any, payload: any) {


        const options = {
            url: encodeURI(urlbase + "wp-json/jwt-auth/v1/token"),
            headers: { 'Content-Type': 'application/json' },
            data: payload,
        };
        console.log(options);



        try {


            console.log(CapacitorHttp);
            console.log(CapacitorHttp.post(options));
            const response = await CapacitorHttp.post(options);

            console.log(response);

            if (response.status == 200 || response.status == 201) {


                const config = {
                    url: encodeURI(urlbase + "wp-json/jwt-auth/v1/token/validate"),
                    headers: {
                        "Authorization": `Bearer ${response.data.data.token}`
                    },
                    data: {},
                };
                const validatedToken = await CapacitorHttp.post(config);


                if (validatedToken.data && validatedToken.data.statusCode == 200) {

                    await Preferences.set({
                        key: "access_token",
                        value: response.data.data.token,
                    });

                    /* not yet available (jwt not oauth)
                    await Preferences.set({
                      key: "refresh_token",
                      value: response.data.refresh_token,
                    });*/

                    commit("saveAuthToken", response.data.data);
                    commit("saveLoginStatus", "success");
                } else {

                    commit("saveLoginStatus", "failed");
                }
            }
        } catch (error) {
            console.log(error);
        }
    },
...


The log I obtain:

⚡️  [log] - {"url":"https://staging2.intercambioplus.eu/wp-json/jwt-auth/v1/token","headers":{"Content-Type":"application/json"},"data":{"username":"pierretest","password":"password"}}
⚡️  [log] - {}
⚡️  [log] - {}
Type: stdio

You don’t have await so it isn’t going to log the results.

As a side note, you don’t need to use CapacitorHttp directly in your code. If you want, you can use standard fetch or XMLHttpRequest or axios/axios and the Capacitor plugin will patch/intercept those.

Hello,

I modified the code to try using fetch but I run in the same issue.
No behavior happens.
I don’t see no http call in the Xcode’ network profiler.
I need to catch info on what happens after I call fetch’s http methods.
Any advice on how to do that in Xcode or Ionic ?
Cause right now it feels like sending data to a black hole :stuck_out_tongue:

async loginUser({ commit }: any, payload: any) {

        const options = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: payload
        };
        console.log(options);

        fetch(encodeURI(urlbase + "wp-json/jwt-auth/v1/token"), options)
            .then(async response => {
                if (response.ok) {

                console.log(response);

                    const responseData = await response.json();

                    const config = {
                        method: 'POST',
                        headers: {
                            "Authorization": `Bearer ${responseData.data.token}`
                        }
                    };

                    fetch(encodeURI(urlbase + "wp-json/jwt-auth/v1/token/validate"), config)
                        .then(async validateresponse => {

                            if (validateresponse.ok) {

                                const validatedToken = await validateresponse.json();

                                if (validatedToken.data.statusCode == 200) {

                                    await Preferences.set({
                                        key: "access_token",
                                        value: validatedToken.data.token,
                                    });

                                    commit("saveAuthToken", validatedToken.data);
                                    commit("saveLoginStatus", "success");
                                } else {
                                    commit("saveLoginStatus", "failed");
                                }
                            } else {
                                commit("saveLoginStatus", "failed");
                            }

                        })
                        .catch(e => {
                            console.log(e);
                        })
                } else {
                    console.log(response);
                    commit("saveLoginStatus", "failed");
                }
            })
            .catch(e => {
                console.log(e);
            })
    },

My console logs in the pasted code give nothing except for the first one logging the options object:

⚡️  [log] - {"method":"POST","headers":{"Content-Type":"application/json"},"body":{"username":"pierretest","password":"password"}}
Type: stdio

Not really sure. I did just discover the patching to native libraries is disabled by default though - Capacitor Http Plugin API | Capacitor Documentation.

Hopefully someone else can chime in. It’s definitely odd that it works on Android but not iOS.