Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape angular HttpParams?

Tags:

http

angular

In an Angular Service I'm using HttpParams to send a string to the service:

get(phone: string): Observable<PhoneSearchResponse> {
    let params = new HttpParams();
    params = params.append("phone", phone); // sending "+123456"
    return this._http.get<PhoneSearchResponse>(`${this._apiurl}/Get`, { params: params });
}

When calling get() with +123456 as parameter I'll get 123456 in the receiving service. So somewhere on the way the + gets converted to a space.

Do I need to escape HttpParams to get them unchanged to the service?

If it matters, the backend is an asp.net core project. The called code in the controller:

[HttpGet("[action]")]
public async Task<JsonResult> Get(string phone) // receiving " 123456"
{
  return Json(await PhoneSearchLogic.GetAsync(phone));
}

[Update] Very good explanation by Noémi Salaün - but I wonder if changing the parameters is expecteded behaviour "by design"? Or is the problem the ASP.NET Core controller, which should not unescape the + sign (and others)?

like image 873
Sam Avatar asked Mar 22 '18 21:03

Sam


People also ask

What is HttpParams in angular?

This post is a guide on how to Pass the URL Parameters or Query Parameters along with the HTTP Request using the HttpClient in Angular. We will be using HttpParams to add the URL Parameter, which is then used by the GET , POST , PUT & PATCH etc methods to send an HTTP request to the back end API.

How do you pass multiple parameters in HTTP GET request in angular 8?

Passing multiple parameters to Http get requestBy using HttpParams. append() we can pass multiple parameters to HttpClient. get() method. We have to pass page & per_page parameters to the list of users API.


2 Answers

As you can see in the source code common/http/src/params.ts, HttpParams uses a default encoder HttpUrlEncodingCodec.

HttpUrlEncodingCodec uses the native encodeURIComponent function but then un-encodes some symbole to meet the RFC specification (not followed by the native JS implementation).

So if you want to keep your + symbol encoded you can encode it manually before using HttpParams, or you can override the HttpParameterCodec with your own implementation and pass it through the HttpParamOptions.encoder attribute.

All this was better explained in the now deprecated Http service. With its UrlSearchParams and the QueryEncoder.

As you can see in the source code http/src/url_search_params.ts

By default, QueryEncoder encodes keys and values of parameters using encodeURIComponent, and then un-encodes certain characters that are allowed to be part of the query according to IETF RFC 3986: https://www.rfc-editor.org/rfc/rfc3986.

These are the characters that are not encoded: ! $ \' ( ) * + , ; A 9 - . _ ~ ? /

If the set of allowed query characters is not acceptable for a particular backend, QueryEncoder can be subclassed and provided as the 2nd argument to URLSearchParams.

like image 92
Noémi Salaün Avatar answered Sep 21 '22 19:09

Noémi Salaün


Angular 13 still has this problem. Look at https://github.com/angular/angular/issues/11058 and https://github.com/angular/angular/pull/45111
The solution that worked for me was written by Ali Kamalizade at https://betterprogramming.pub/how-to-fix-angular-httpclient-not-escaping-url-parameters-ddce3f9b8746
The following is his solution. The same solution was suggested by Noémi Salaün in the accepted answer of this question.

import { HttpParameterCodec } from '@angular/common/http';
export class CustomHttpParamEncoder implements HttpParameterCodec {
    encodeKey(key: string): string {
        return encodeURIComponent(key);
    }
    encodeValue(value: string): string {
            return encodeURIComponent(value);
    }
    decodeKey(key: string): string {
            return decodeURIComponent(key);
    }
    decodeValue(value: string): string {
            return decodeURIComponent(value);
    }
}

You can use it when you create a HttpParams.

 HttpParams({ encoder: new CustomHttpParamEncoder() })
like image 33
rickz Avatar answered Sep 19 '22 19:09

rickz