http icon indicating copy to clipboard operation
http copied to clipboard

Different behaviour on IOS/Android/Browser with stringified and empty JSON body at post requests

Open mobilemarines opened this issue 4 years ago • 4 comments

Describe the bug While switching from Angular Http to this Capacitor Http plugin we noticed two problems:

Problem 1: Different behaviour when passing stringified JSON body:

  • On Android, if a JSON body of type string is passed to HTTP.post, it is serialised correctly and sent as a JSON object in the body of the post request.
  • With IOS and Browser, the JSON body of type string is not serialised and is sent as a stringified payload. Therefore, the body must be parsed as a JSON object before it is set.
  • The serialisation of a passed JSON body of type string only works on Android. Is it a bug or is a stringified JSON body explicitly not supported?

Problem 2: Sending empty/undefined payload in post requests:

  • In our implementation, when sending a post request, it can happen that the body of a post request is empty/undefined.
  • This is not a problem with Android / Browser. The request is sent to the defined interface without any payload.
  • When sending a post requests without body on IOS, a request error occurs.
  • Therefore, a workaround is currently required for IOS, which sends a dummy JSON object to avoid an empty body.

To Reproduce

Problem 1:

  1. Setup a Http post request
  2. Create a stringified JSON body, which is set as the body of the HTTP post request.
  3. Run request on Browser, Android, IOS
  4. On Android, the JSON body is serialised correctly and sent in the JSON object. On Browser/IOS, the body is not serialised and is sent as a string.

Problem 2:

  1. Setup a Http post request
  2. The data of the post request is not set (undefined).
  3. Run request on Browser, Android, IOS
  4. On Android/Browser the request is sent with an empty body. With IOS this results in a request error.

Expected behavior

The behaviour should be the same for IOS/Android/Browser.

Problem 1:

  • The stringified JSON body of a post request should be serialised correctly on all three platforms.

Problem 2:

  • If a post request is created with an empty body (undefined), the request should be sent with an empty payload. This should also work with IOS.

Desktop/Smartphone(Emulator):

Tested on:

Android: - OS: Windows - Emulator: Pixel 4 API 30

IOS: - OS: macOS Catalina 10.15.7 - Emulator: iPhone 11 - 14.4

Browser: - Google Chrome - Version: 93.0.4577.82

mobilemarines avatar Sep 22 '21 10:09 mobilemarines

I had a similar problem. The request works fine in the browser, but on Android the request body is always empty. Then I try this

import { Capacitor } from "@capacitor/core";
import { Http } from "@capacitor-community/http";

function fetch2(url, options = {}) {
    options.url = url;
    options.method = options.method || "GET";
    if (options.body || options.method == "POST") {
        if (Capacitor.isNativePlatform() == true) {
            options.headers = { "content-type": "application/json" };
        }
        options.data = options.body;
        delete options.body;
    }
    return Http.request(options);
}

and everything worked.

AlexRMU avatar Oct 07 '21 14:10 AlexRMU

I can confirm this is an issue, which can be fixed by setting the "content-type" header to "application/json". Replicated it and fixed it on my own app. Works fine in the browser but oddly sends an empty request on android.

ooojustin avatar Oct 22 '21 03:10 ooojustin

I also experienced Problem 1.

In HttpOptions, I had set:

data: data

This worked on Android and in the browser (Chrome), but not on iOS.

The IOS error was simply Error REQUEST, which didn't give me enough information to solve the problem.

When I changed it to:

data: JSON.stringify(data)

it worked on all three platforms.

Definitely it would be great to get consistent error messages for this kind of thing.

ptmkenny avatar Oct 25 '21 07:10 ptmkenny

I can confirm this is the same behaviour on iOS. The data is sent as empty. Resolved it by applying the "content-type": "application/json" to the header.

I cannot find anything in the example or docs which state you have to specify the content-type, unless im looking in the wrong place?

Wahsner avatar Oct 26 '21 13:10 Wahsner