Angular URL-адрес плюс преобразование знака в космос
У меня есть приложение angular, где я хочу передать знак + в строке запроса, например:
http://localhost:3000/page?name=xyz+manwal
Когда я нажимаю на этот URL-адрес, он конвертируется в:
http://localhost:3000/page?name=xyz%20manwal
Где %20 относится к пробелу
. Как я могу предотвратить это преобразование?
Ответы
Ответ 1
Я нашел решение и разместил его для дальнейшего использования. Angular js преобразовывал знак +
в %2B
.
Следующий код предотвратил:
.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;
});
}
])
Ответ 2
Вы можете переопределить угловое кодирование по умолчанию, добавив Interceptor, который исправляет это:
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);
}
}
и объявите это в разделе провайдеров в app.module.ts
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: EncodeHttpParamsInterceptor,
multi: true
}
]
Ответ 3
Это общая проблема. Символ +
используется URL для разделения двух слов. Чтобы использовать символ +
в значениях параметров, вам необходимо закодировать значения параметров перед добавлением их как части URL. Javascript/TypeScript предоставляет функцию encodeURI()
для этой конкретной цели.
URL-кодирование преобразует символы в формат, который может быть передан по Интернету. [w3Schools Reference]
Вот как вы можете исправить эту проблему:
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 }`;
Таким же образом вы можете декодировать параметры с помощью метода decodeURI()
.
let decodedValue = decodeURI(encodedValue);
Ответ 4
В Angular 5.2. 7+ "+" заменяется пробелом "" в строке запроса.
Вот соответствующий коммит: fix (router): исправить сериализацию URL
Если вы хотите изменить это поведение и заменить "+" на "%2B", вы можете создать собственный сериализатор URL-адресов и предоставить его поставщикам AppModule.
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
URL будет преобразован в:
http://localhost:3000/page?name=xyz%2Bmanwal
Надеюсь, это поможет.
Ответ 5
Это довольно распространенная проблема. Вы можете передать его обычно в запросе application/x-www-form-urlencoded. Ни один другой запрос не сможет правильно разобрать+. Они всегда будут анализировать его на %20 вместо% 2B.
Вам нужно будет вручную манипулировать параметром запроса, есть два способа:
- Кодировать параметр в кодировке base64, таким образом, никакой специальный символ не может разорвать ваше приложение, но вам нужно будет обрабатывать его также в принимающей части (декодировании).
- Более простые решения будут, прежде чем удалять URL, заменить все знаки + на% 2B. Таким образом, другая сторона сможет декодировать ее нормально, без необходимости специальной процедуры.
Для получения дополнительной информации вы должны ответить на следующие вопросы о переполнении стека Android: как разобрать URL-адрес String с пробелами для объекта URI? и URL-кодирование символа пробела: + или %20?
Ответ 6
В Angular v6.1.10, если вам просто нужно исправить кодировку знака "+" в одном месте, это то, что сработало для меня.
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);
}
Я обнаружил, что если вы пытаетесь заменить знаки "+" при инициализации объекта httpParams
, он не работает. Вы должны выполнить замену после преобразования httpParams
в строку, как показано в этой строке:
let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');