Solvedangular HttpRequest.clone is duplicating query parameters (type 'append')

I'm submitting a...

[ ] Regression (a behaviour that used to work and stopped working in a new release)
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behaviour

Using the new HttpClient HttpRequest.clone() duplicates existing query parameters

As an example, the following interceptor simply adds a query param. As an unwanted side effect of the clone method, existing query params get duplicated:

    intercept(
        req: HttpRequest<any>,
        next: HttpHandler
    ): Observable<HttpEvent<any>> {

            req = req.clone({
                setParams: {
                    locale: this.translate.currentLang
                }
            });
        return next.handle(req);
    }

In essence: ?sort=id,asc becomes :
?sort=id,asc&sort=id,asc&locale=en
instead of
?sort=id,asc&locale=en
when the query gets executed.

Expected behavior

HttpRequest.clone() should not duplicate existing query parameters in the request.

req = req.clone({
                setParams: {
                    locale: this.translate.currentLang
                }
            });

Note: The query parameters where added using HttpParams.append(...) as there indeed could exist multiple query params, but of course not with the same content.

Minimal reproduction of the problem with instructions

    let params = new HttpParams();
    
    params = params.append('sort', 'id,asc');
    
    let req2 = new HttpRequest('GET', 'url', null, {
        params: params
    });
    let clone = req2.clone({
        setParams: {
            locale: 'de'
        }
    });
    this.dump = JSON.stringify(clone.params);

See this plunker: https://plnkr.co/edit/mqJCe7QbUWpzWQNbeOJS?p=preview

What is the motivation / use case for changing the behaviour?

Duplicate query params cause errors in the backend.

Environment

Angular version: 4.3.5

Browser:

  • Chrome (desktop) version XX
  • Chrome (Android) version XX
  • Chrome (iOS) version XX
  • Firefox version XX
  • Safari (desktop) version XX
  • Safari (iOS) version XX
  • IE version XX
  • Edge version XX

Seems not to be browser related.

For Tooling issues:

  • Node version: 4.7.0
  • Platform: 5.3.0

Others:

17 Answers

✔️Accepted Answer

Figured out a lightweight workaround. Instead of using setParams: just replace the params entirely with params: which accepts HttpParams. (Reference)

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // Keeps the original request params. as a new HttpParams
  let newParams = new HttpParams({fromString: request.params.toString()});

  // Add any params (can also chain .append() but I was conditionally adding params)
  newParams = newParams.append('new_param', 'param_value');
  newParams = newParams.append('another_param', 'another_value');

  // Clone the request with params instead of setParams
  const requestClone = request.clone({
    params: newParams
  });

  return next.handle(requestClone);
}

Hope this helps anyone who comes across this until there is a fix.

More Issues: