HTTP Post with form data on iOS renders an incomplete request body when ‘=’ character exists anywhere in the form data.

Environment Info:
cli packages:

@ionic/cli-utils  : 1.19.2
ionic (Ionic CLI) : 3.20.0

global packages:

cordova (Cordova CLI) : 8.1.2 (cordova-lib@8.1.1) 

local packages:

@ionic/app-scripts : 3.1.8
Cordova Platforms  : ios 4.5.5
Ionic Framework    : ionic-angular 3.9.2

System:

ios-sim : 6.1.2
Node    : v10.12.0
Npm     : 6.4.1
OS       : macOS High Sierra
Xcode  : Xcode 9.4 Build version 9F1027a 

Relevant plugins:

cordova-plugin-advanced-http 1.11.1
cordova-plugin-ionic-webview 1.2.1

@angular/http 5.0.3
@ionic-native/http 4.5.3
ionic-native-http-connection-backend 4.0.3

We are attempting to use http.post to send some form data as json. When any string in that json contains an “=” character, http.post seems to be mangling it. The server on the other end only receives the post body up until the point of the “=” character with nothing else afterward.

This issue only happens with ios; our android, chrome and windows builds all function without a problem. We suspect that this is heavily related to the combination of the cordova-plugin-ionic-webview and cordova-plugin-advanced-http plugins and the ionic-native-http-connection-backend which only come into play on ios. We updated our app to use the webview plugin to address some performance concerns. However, after switch to that library we found that it broke every network transaction with CORS issues and other problems, which eventually lead us to using the other libraries mentioned in this ticket.

Here is a simplified example of hour our http post code:

import { Headers, Http, RequestOptions, URLSearchParams } from ‘@angular/http’;

  const post_payload = {
    parameter: 'example = string'
  };
  const data = new URLSearchParams();
  data.append('post', JSON.stringify(post_payload));
  const options = new RequestOptions({
    headers: headers,
    withCredentials: true
  });
  this.http.post('https://example.url', data.toString(), options)
  .subscribe(response => {
    //handle response
  }, (error) => {
    //handle error
  });

The post request completes, but the post body renders as:
{post: {parameter: ‘example

We have also tried adding the post_payload directly to the data.append(), we have tried forgoing URLSearchParams() entirely and just adding the post_payload object directly and after having been stringified, and we’ve also tried sending the data object without a toString().

Here is what our app.module.ts looks like:

import { HttpModule, JsonpModule } from ‘@angular/http’;
import { NativeHttpFallbackD, NativeHttpModuleD } from ‘ionic-native-http-connection-backend’;
import { Http, RequestOptions } from ‘@angular/http’;

providers: [
DatePicker,
StatusBar,
SplashScreen,
Device,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
Camera,
CameraPreview,
File,
FilePath,
FileTransfer,
MediaCapture,
{provide: Http, useClass: Http, deps: [NativeHttpFallbackD, RequestOptions]}
]

I’ve tried bringing all relevant plugins and libraries up to the most recent version. I’ve tried removing the ionic-native-http-connection-backend (but this causes lots of CORS issues and causes http calls to not share cookies with file-transfer plugin which is itself stalled on being replaced because we can’t get blob data transfers to function).

Right now I’m at a loss where to continue to look. Our android and windows builds simply do not contain the bottom “provide” line in app.module.ts and these posts are working without an issue, which leads us to believe that it’s the ionic-native-http-connection-backend library causing the issue. However we can’t remove that library because it is the only thing which seems to allow our CORS requests to succeed when we’re using cordova-plugin-ionic-webview which is a hard requirement at the moment.

Hi @daustinstreamlinx,

Have you tried using encodeURIComponent on the form data before sending it? Most clients do this automatically, but maybe this plugin isn’t.

As you may know, the ?, & and = signs are used to delimit form fields and may be truncating the data parsed by the server.

The other solution is to fix the root CORS issues on the server. Check out the new CORS Errors page in the docs to find an appropriate solution for your use case.

Best,
Rodrigo