Преобразовать команду curl в RestTemplate - PullRequest
1 голос
/ 31 мая 2019

У меня есть следующее выражение curl:

curl --data 'api_key=API_Key' --data-urlencode 'event=[{"user_id":"12345", "event_type":"buy_song"}]' https://someapi

, который должен быть преобразован в вызов RestTemplate.postForEntity. Я делаю преобразование таким образом:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("api_key", "API_Key");
params.add("event", URLEncoder.encode(objectMapper.writeValueAsString(Collections.singletonList(e)), "UTF-8"));

// send
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
ResponseEntity<String> response = restTemplate.postForEntity("https://someapi", request, String.class);

Сервер возвращает 400 Неправильный запрос

Я подтверждаю, что объектный картограф Джексона правильно сериализует объект objectMapper.writeValueAsString(Collections.singletonList(e))

Я подозреваю, что не могу правильно обработать смесь --data и --data-urlencode из примера curl в RestTemplate.

Не могли бы вы подсказать, что я делаю не так?

Ответы [ 3 ]

1 голос
/ 31 мая 2019

У меня отлично работает:

Вот код с клиентом и запросом, пожалуйста, игнорируйте подписи запроса

curl -X GET \
  http://localhost:8080/article/so \
  -H 'cache-control: no-cache' \
  -d 'api_key=API_Key&event=%5B%7B%22user_id%22%3A%2212345%22%2C%20%22event_type%22%3A%22buy_song%22%7D%5D'

Контроллер: Первый запрос вызовет ваш код:

// This is just to trigger, you can ignore it.

    @RequestMapping(value = "/article/so", method = RequestMethod.GET)
    public void addArticle1() throws UnsupportedEncodingException, JsonProcessingException {
        articleServiceImpl.test();
    }

Вышеупомянутый запрос перейдет на уровень обслуживания, где код такой же, как у вас.


    public void test() throws JsonProcessingException, UnsupportedEncodingException {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        Event e = new Event();
        e.setEvent_type("buy_song");
        e.setUser_id("12345");

        params.add("api_key", "API_Key");
        String encode = URLEncoder.encode(objectMapper.writeValueAsString(Collections.singletonList(e)), "UTF-8");
        params.add("event", encode);

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.postForEntity("http://localhost:8080/article/so", request, String.class);
        System.out.println(response);//<200,[Content-Length:"0", Date:"Fri, 31 May 2019 09:26:24 GMT"]>
    }

Затем снова контроллер, просто чтобы проверить, принимает ли контроллер объект String или объект Event от вызывающей стороны.Здесь Event передается как URLEncodedString, который я получаю здесь в качестве вывода.

    @RequestMapping(value = "/article/so", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public void addArticle2(@RequestParam String api_key,@RequestParam String event) {
        System.out.println(api_key); // API_Key
        System.out.println(event); // %5B%7B%22user_id%22%3A%2212345%22%2C%22event_type%22%3A%22buy_song%22%7D%5D
    }

1 голос
/ 31 мая 2019

Я думаю, что единственная проблема - MediaType, данные, которые вы отправляете, не являются данными формы (APPLICATION_FORM_URLENCODED)

Это данные JSON, поэтому вам нужно использовать MediaType.APPLICATION_JSON Как-то так

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

// converting form variable to Map
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("api_key", "API_Key");
map.add("event", URLEncoder.encode(objectMapper.writeValueAsString(Collections.singletonList(e)), "UTF-8"));

// finally build Request
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

ResponseEntity<String> response = restTemplate.postForEntity(
  apiUrl, request , String.class);

См. this для более подробной информации о RestTemplate

1 голос
/ 31 мая 2019
  // org.apache.commons.collections.map.HashedMap     
  HashedMap requestBody = new HashedMap();
      requestBody.put("api_key", "API_Key");
      requestBody.put("event", URLEncoder.encode(objectMapper.writeValueAsString(Collections.singletonList(e)), "UTF-8"));   

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
       String jsonBody = new ObjectMapper().writeValueAsString(requestBody);
       HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);

        ResponseEntity<String> response = restTemplate.postForEntity("https://someapi", entity, String.class);
...