Angular url plus sign converting to space

2019-02-11 14:41发布

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?

5条回答
迷人小祖宗
2楼-- · 2019-02-11 15:13

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
    }
]
查看更多
仙女界的扛把子
3楼-- · 2019-02-11 15:15

I have found solution and posting it for future reference. Angular js was converting + sign into %2B.

Following code prevented that:

.config([
    '$provide', function($provide) {
      $provide.decorator('$browser', function($delegate) {
        let superUrl = $delegate.url;
        $delegate.url = (url, replace) => {
          if(url !== undefined) {
            return superUrl(url.replace(/\%2B/g,"+"), replace);
          } else {
            return superUrl().replace(/\+/g,"%2B");
          }
        };
        return $delegate;
      });
    }
  ])
查看更多
何必那么认真
4楼-- · 2019-02-11 15:21

This is a quite common problem. You can pass it normally in application/x-www-form-urlencoded request. No other request will be able to correctly parse +. They will always parse it into %20 instead of %2B.

You would need to manually manipulate the query parameter, there are 2 ways:

  • Encode the parameter into base64 encoding, this way no special character can break you application, but you would need to handle it also on the receiving part (decoding).
  • A simplier solutions would be, before hitting the URL, replace all + signs with %2B. This way the other side will be able to decode it normaly, without the need of a special routine.

For more info you should reffer to hthe following stack overflow questions Android: howto parse URL String with spaces to URI object? and URL encoding the space character: + or %20?

查看更多
欢心
5楼-- · 2019-02-11 15:26

This ia a common problem. The + character is used by the URL to separate two words. In order to use the + character in the parameter values, you need to encode your parameter values before adding them as part of the URL. Javascript / TypeScript provide a encodeURI() function for that specific purpose.

URL encoding converts characters into a format that can be transmitted over the Internet. [w3Schools Reference]

Here is how you can fix this problem:

let encodedName = encodeURI('xyz+manwal');
let encodedURI = 'http://localhost:3000/page?name='+encodedName;

//.. OR using string interpolation
let encodedURI = `http://localhost:3000/page?name=${ encodedName }`;

In the same way, you can decode the parameters using decodeURI() method.

let decodedValue = decodeURI(encodedValue);
查看更多
混吃等死
6楼-- · 2019-02-11 15:33

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.

查看更多
登录 后发表回答