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');