Как избежать двойного кодирования [] при использовании Spring RestTemplate? - PullRequest
0 голосов
/ 24 марта 2020

У меня есть приложение Spring Boot 2.2.5, вызывающее эту конечную точку REST

@RequestMapping(path = "/usable/search")
public List<Provider> findUsable(
      @RequestParam(name = "country-id", required = false) Integer countryId,
      @RequestParam(name = "network-ids[]", required = false) List<Integer> networkIds,
      @RequestParam(name = "usages[]") Set<Usage> usages)

Мой абонент делает

val url = clientUri.toString() + configuration.getUrl().getUseableProvidersForNetworks(); % 'providers/usable/search?'
val builder = UriComponentsBuilder.fromHttpUrl(url)
      .queryParam("usages[]", USAGES)
      .queryParam("network-ids[]", networkIds);
val response =
      restTemplate.exchange(
          builder.toUriString(),
          HttpMethod.GET,
          entity,
          new ParameterizedTypeReference<List<Provider>>() {});

, где USAGES - это Set<Usage> и networkIds является List<Integer>.

Шаблон RestTemplate создается

RestTemplate eurekaRestTemplate() {
    val requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setReadTimeout(TIMEOUT);
    requestFactory.setConnectTimeout(TIMEOUT);
    return new RestTemplate(new BufferingClientHttpRequestFactory(requestFactory));
  }

Проблема: [] получает двойное кодирование в %255B%255D, и я заканчиваю вызовом

providers/usable/search?usages%255B%255D=MESSAGE_DELIVERY&network-ids%255B%255D=2145118475&network-ids%255B%255D=-1536358371

Что явно не работает; сервер пропускает, например, usages[]. Он работает с curl с [] вместо %255B%255D.

Как этого избежать?

Я знаю эту проблему и документы , но это еще не помогло.

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Решением было вызвать UriComponentsBuilder.build(false), чтобы указать UriComponentsBuilder , а не для кодирования URL:

val response = restTemplate.exchange(
              builder.build(false).toUriString(),
              HttpMethod.GET,
              entity,
              new ParameterizedTypeReference<List<Provider>>() {});

Это сложно, потому что тест с Mockito / JUnit этого скажет вам, что URL не закодирован, в то время как тест с MockRestServiceServer покажет один уровень кодирования ([] становится %5B%5D).

1 голос
/ 24 марта 2020

Я думаю, вы не должны иметь дело с использованием []. Я имею в виду, что нет необходимости называть ваши параметры, используя "[]". Зачем вам это делать?

val builder = UriComponentsBuilder.fromHttpUrl(url)
      .queryParam("usages", USAGES)
      .queryParam("network-ids", networkIds);

отлично подойдет для:

public List<Provider> findUsable(
      @RequestParam(name = "country-id", required = false) Integer countryId,
      @RequestParam(name = "network-ids", required = false) List<Integer> networkIds,
      @RequestParam(name = "usages") Set<Usage> usages)

Надеюсь, это поможет!

Подсказка: будьте осторожны при использовании параметров массива / коллекции на URL, есть ограничение длины URL, которое вы должны учитывать

...