Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpClient - incorrect ContentType for boolean #38924

Closed
devxzero opened this issue Sep 21, 2020 · 6 comments
Closed

HttpClient - incorrect ContentType for boolean #38924

devxzero opened this issue Sep 21, 2020 · 6 comments
Labels
area: common/http P4 A relatively minor issue that is not relevant to core functions state: confirmed
Milestone

Comments

@devxzero
Copy link

🐞 bug report

Affected Package

The issue is caused by package @angular/common/http

Is this a regression?

No.

Description

TLDR:

A boolean as body is seen as text/plain where is should be seen as application/json, since it is valid JSON, like numbers. See:
https://jsonlint.com/
https://www.json.org/json-en.html

Detailed description:

The post() method of HttpClient (and other request methods) accept a body method argument of type any. When the HTTP request is about to execute, HttpClient will determine the content type of body, so that it can set the Content-Type header to for example application/json or text/plain.

When an object is used as body, HttpClient will send it as application/json as expected.

When a plain number is used as body (e.g. 123, without quotes), HttpClient will also send it as application/json, because even a plain number (without curly braces and without quotes) is valid JSON.

When a TypeScript string is used as body argument (e.g. "abc"), HttpClient will send it as text/plain because it will be send without quotes in the HTTP request body, and thus isn't valid JSON. So it will use text/plain as expected.

But when boolean is used, this behavior is different. When a plain boolean (e.g. true) is used as body argument, HttpClient will send it as text/plain even though a simple plain boolean is valid JSON.

The code where this problems is caused is:

if (typeof this.body === 'object' || typeof this.body === 'number' ||

    // Arrays, objects, and numbers will be encoded as JSON.
    if (typeof this.body === 'object' || typeof this.body === 'number' || Array.isArray(this.body)) {
      return 'application/json';
    }

Plain objects, numbers, booleans and arrays values are all valid JSON code. Whereas a plain string without quotes it not valid JSON.
So plain objects, numbers, booleans and arrays values should be send as application/json and strings as text/plain. But in HttpClient this behavior unexpectedly differs for booleans.

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-ivy-umexba?file=src/app/app.component.ts

import { Component, VERSION } from '@angular/core';
import {HttpClient} from '@angular/common/http';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="sendObject()">Send object</button>
    <button (click)="sendNumber()">Send number</button>
    <button (click)="sendBoolean()">Send boolean</button>
    <button (click)="sendString()">Send string</button>
  `
})
export class AppComponent  {
  constructor(private httpClient: HttpClient) {}

  sendObject() {
    // 'application/json'
    this.httpClient.post<any>("http://localhost", {x: 1}).subscribe();
  }

  sendNumber() {
    // 'application/json'
    this.httpClient.post<any>("http://localhost", 123).subscribe();
  }

  sendBoolean() {
    // `text/plain`, but should be 'application/json'
    this.httpClient.post<any>("http://localhost", true).subscribe();
  }

  sendString() {
    // `text/plain`
    this.httpClient.post<any>("http://localhost", "abc").subscribe();
  }
}

🌍 Your Environment

Angular Version:

10.1.2
@ngbot ngbot bot added this to the needsTriage milestone Sep 21, 2020
@atscott atscott added P4 A relatively minor issue that is not relevant to core functions state: confirmed labels Oct 21, 2020
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Oct 21, 2020
@atscott
Copy link
Contributor

atscott commented Oct 21, 2020

Yep, it looks like you're right. Thanks for the detailed explanation and examples; it makes reports like this really simple to evaluate. I'm setting the priority pretty low though because the recommendation is to not use texts that are neither objects nor arrays:

However, there are software
implementations, coded to the older specification [RFC4627], which
only accept JSON objects or JSON arrays at the top level of JSON
texts. For maximum interoperability with such implementations,
protocol designers SHOULD NOT use top-level JSON texts that are
neither objects nor arrays.

@gopal-jayaraman
Copy link
Contributor

Looks like this issue was already fixed, is there any other reason why this is still open?
Screen Shot 2021-04-29 at 3 59 17 PM

@atscott
Copy link
Contributor

atscott commented Apr 29, 2021

@gopal-jayaraman - This report is for boolean, not number. So the code is missing || typeof this.body === 'boolean'

@gopal-jayaraman
Copy link
Contributor

Thanks for the info @atscott , I will be raising a PR for this.

gopal-jayaraman added a commit to gopal-jayaraman/angular that referenced this issue Apr 29, 2021
… request body(angular#38924)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.
gopal-jayaraman added a commit to gopal-jayaraman/angular that referenced this issue Apr 29, 2021
… request body(angular#38924)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.
gopal-jayaraman added a commit to gopal-jayaraman/angular that referenced this issue Apr 29, 2021
… request body(angular#38924)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.
gopal-jayaraman added a commit to gopal-jayaraman/angular that referenced this issue Apr 30, 2021
… request body(angular#38924)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.
gopal-jayaraman added a commit to gopal-jayaraman/angular that referenced this issue Apr 30, 2021
… request body(angular#38924)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.
mhevery pushed a commit that referenced this issue May 3, 2021
… request body(#38924) (#41885)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.

PR Close #41885
mhevery pushed a commit that referenced this issue May 3, 2021
… request body(#38924) (#41885)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.

PR Close #41885
mhevery pushed a commit that referenced this issue May 3, 2021
… request body(#38924) (#41885)

currently a boolean as body is seen as text/plain, where is should be seen as application/json, since it is valid JSON, like numbers.

PR Close #41885
@JoostK
Copy link
Member

JoostK commented May 7, 2021

This was fixed in #41885 in Angular 11.2.13!

@JoostK JoostK closed this as completed May 7, 2021
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jun 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: common/http P4 A relatively minor issue that is not relevant to core functions state: confirmed
Projects
None yet
Development

No branches or pull requests

5 participants