Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ngx-http-client

Angular (4.3+) HttpClientModule with parameter encodings compatible with back ends (Node.js, Python, PHP, etc).

Notice

This package was made to be a quick workaround while the fix in Angular itself was merged, in the PR #19710.

That PR was created at 2017-10-13. As of 2019-10-19 (2+ years after), it's still waiting to be merged.

This package has some older dependencies, but I'm not currently using Angular.

If you are needing this, the best would be to write a comment in that PR, add a code review approving it, etc. Try to get the attention from the Angular team to accept that PR.

You can also consider other alternatives, like:

  • Vue:
    • It's a lot easier to learn.
    • Has less code duplication.
    • Doesn't force RxJS if you don't need it.
    • But editor support in the templates is not as good as with Angular in VS Code.
  • React:
    • Specifically, modern React, using create-react-app with TypeScript and using Hooks.
    • It's easier to learn.
    • Has less code duplication.
    • Doesn't force RxJS if you don't need it.
    • Editor support, including JSX, is strangely superb, when using TypeScript and Hooks.
    • But you have to use JSX, which you might not like if you haven't really tried it yet, or if you used React before it had support for TypeScript and Hooks.

How to use

  • Install it in your Angular project:
npm install --save ngx-http-client
  • Follow Angular's guide on HttpClient.
  • At some point, in one single place in your code, most probably in a file app.module.ts, the guide will tell you to import HttpClientModule like:
import {HttpClientModule} from '@angular/common/http';
  • Replace that HttpClientModule for the one from this package, like:
// import {HttpClientModule} from '@angular/common/http';

import {HttpClientModule} from 'ngx-http-client';

And that's it. You only have to change that line above. And you can continue using HttpClient as normally. In the rest of your code (your components and services) you should import HttpClient from Angular as normally:

// This line would look the same with or without installing this package
import { HttpClient } from '@angular/common/http';

The problem

If you use the normal HttpClientModule, at some point you might want to send parameters in your URL.

Let's say that you want to send the time zone of the user as a parameter timezone. And one of your users has a time zone of +03:00 UTC.

Your code uses the HttpClient normally, for example:

this.http.get('http://example.com', {
      params: {
        timezone: userTimezone,
      }
    }).subscribe(
        ...
    )

Your front end will send the timezone to the back end like:

http://example.com?timezone=+03:00

But your back end (be it Node.js, Python, PHP or several others) will receive that parameter like:

{
    "timezone": " 03:00"
}

...because it will interpret the raw + sign as a replacement for a space.

But you need your back end to see it as:

{
    "timezone": "+03:00"
}

For that, your front end (your Angular app, using HttpClientModule ) should encode it like:

http://example.com?timezone=%2B03%3A00

This package makes HttpClientModule encode + and all the special characters in the way the back end systems can understand them.

That's the most simple and straightforward example. But the same kinds of problems might occur for these other characters:

@ : $ , ; + = ? /

Warning note

There are some back end systems that expect you to send the raw, unencoded characters. In those cases, you might try to use the standard HttpClientModule or maybe even better, form the complete URL in your side, making sure that you encode everything as expected by the specific back end in your code.

Very technical details

Note: You most probably don't need to read this part. The problem actually goes to the deep roots of the web itself. If you want to know all the details, continue reading.

The HttpClient from Angular inherited previous code from @angular/http.

The previous code was modified to decode those special characters after being encoded by the browser's JavaScript encodeURIComponent.

The code has a comment citing IETF RFC 3986, claiming that it re-decodes the characters because they "are allowed to be part of the query".

The RFC only says that the query component allows several characters in "the query component". But it refers to the query component as everything that goes after the ? and before the #. So, it specifies which characters are allowed in that whole string, but it doesn't refer to how to encode keys and values inside that query string.

I think that the Angular implementation was assuming that those characters where the ones allowed for parameter key and values separated by =. But that same assumption would imply that if you want to send a parameter user with value age=20 that would mean that the URL would be written as:

http://example.com?user=age=20

How should a back end interpret that? Is there a parameter age with value 20? Now imagine what would happen if the value of a parameter was a string including &.

The W3C (World Wide Web), directed by the same person that created the RFC from above, the HTML standard and the HTTP protocol (the inventor of the web, Sir Tim Berners-Lee), said later that "Within the query string, the plus sign ( + ) is reserved as shorthand notation for a space. Therefore, real plus signs must be encoded." (In the "Query strings" section).

Apart from that, there is no standard on how to encode parameters in the "query component" of a URL (the section after the ? until a # character or the end of the string). Specifically, there is no standard on how to encode keys or values.

Browsers have a encodeURIComponent that converts a string with special characters (like the ones above) into an encoded string. That allows URLs to have values with strings that have characters that otherwise would have a special meaning. E.g. separating a parameter key from a parameter value ( "=" would be encoded as "%3D" ), separating a parameter key-value pair from another ( "&" would be encoded as "%26" ), including a space character inside the string ( "+" would be encoded as "%2B" and the space character " " as "%20" ), etc. And although the encodeURIComponent function would encode a literal space character as %20, most back end languages would also interpret the + symbol as a replacement of a space character.

Several (most) programming languages parse URL parameters decoding the key and value pairs using a compatible (or the same) encoding system.

As a result, if you have a back end in Node.js, Python, PHP or several others, the language will expect to parse the query component of the URL as a mapping of parameter keys to values, with the keys and values encoded using that standard or a compatible one.

There is a PR to Angular with the same code changes in this package. But up to the date of publishing this package, it has not received any attention.

There are also several - long - threads related to this - same - problem in issues of the Angular GitHub repository with even discussion about the problem.

About

Angular (4.3+) HttpClientModule with parameter encodings compatible with back ends (Node.js, Python, PHP, etc)

Resources

License

Packages

No packages published