Angular url plus sign converting to space

Viewed 51097

I have angular application where i want to pass plus sign + in query string like:

http://localhost:3000/page?name=xyz+manwal

When I am hitting this URL its converting to:

http://localhost:3000/page?name=xyz%20manwal

Where %20 refer to space . How can I prevent this conversion?

11 Answers

You can override default angular encoding with adding Interceptor which fixes this:

import { HttpInterceptor, HttpRequest, HttpEvent, HttpHandler, HttpParams, HttpParameterCodec } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";

@Injectable()
export class EncodeHttpParamsInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const params = new HttpParams({encoder: new CustomEncoder(), fromString: req.params.toString()});
    return next.handle(req.clone({params}));
  }
}


class CustomEncoder 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);
  }
}

and declare it in providers section of in app.module.ts

providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: EncodeHttpParamsInterceptor,
      multi: true
    }
]

In Angular 5.2.7+ the "+" is replaced with space " " in a query string.

Here is the corresponding commit : fix(router): fix URL serialization

If you want to change this behaviour and replace the "+" with "%2B" you can create a custom url serializer and provide it in the AppModule providers.

import { DefaultUrlSerializer, UrlSerializer, UrlTree } from '@angular/router';

export default class CustomUrlSerializer implements UrlSerializer {
    private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();

    parse(url: string): UrlTree {
        // Encode "+" to "%2B"
        url = url.replace(/\+/gi, '%2B');
        // Use the default serializer.
        return this._defaultUrlSerializer.parse(url);
    }

    serialize(tree: UrlTree): string {
        return this._defaultUrlSerializer.serialize(tree).replace(/\+/gi, '%2B');
    }
}

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent
    ],
    providers: [
        { provide: UrlSerializer, useClass: CustomUrlSerializer }
    ],

    entryComponents: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

http://localhost:3000/page?name=xyz+manwal

The URL will be converted to:

http://localhost:3000/page?name=xyz%2Bmanwal

Hope this will help.

In Angular v6.1.10, if you just need to fix the "+" sign encoding in one spot, this is what worked for me.

getPerson(data: Person) {

  const httpParams = new HttpParams({
    fromObject: {
      id: data.id,
      name: data.name,
      other: "xyz+manwal"
    }
  });

  // manually encode all "+" characters from the person details
  let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');

  return this.http.get(url);
}

I found if you try to replace the "+" signs when initializing the httpParams object it doesn't work. You have to do the replacement after converting httpParams to a string, as shown on this line:

let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');

I am using Angular 7, the + (this one "xyz+manwal") is replaced with a space (like this "xyz manwal") in the URI when it reaches to back-end code.

encodeURI() dindn't work for me, I used encodeURIComponent() it converted + to %2B

     encodeURIComponent("xyz+manwal") => "xyz%2Bmanwal"

below is the example code

    // filter = xyz+manwal
    let filterString =  encodeURIComponent(filter); // filterString = xyz%2Bmanwal

    return this.http.get<ListResults>("http://website/query-results?" + filterString ).pipe(
      retry(3),
      catchError(........)
    )

Use new HttpUrlEncodingCodec().encodeValue("+91")

Below code can help: by adding("-")

queryParams: {
    category: product.category,
    '': product.title.toString().replace(/\s/g, '-')
}

Use JavaScript function: encodeURIComponent().

In this case, encode string as : encodeURIComponent("xyz+manwal"). output will be xyz%2Bmanwal

We solved this problem by converting the way we marshal the data up to the server. Instead of sending it as querystring parameters on the target URL we are now posting the data in the body of the http request. Data passed on the querystring is exposed to all the risks of the transport; encoding conversion and also the risk of exceeding the legal length of the URL. Sending the data within the body eliminates these issues.

Of course, this isn't relevant if you need the data on the URL. But if you don't need the data on the URL, transporting the data values on the URL as opposed to within the body is like duct-taping yourself to the wing, when you could be riding in coach! :-)

Anyway, this solved our problem. I hope this can help solve yours.

Related