2

I have the following curl expression:

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

which should be converted into RestTemplate.postForEntity call. I do conversion this way:

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

Server returns 400 Bad request

I confirm that Jackson's objectmapper serializes the object correctly objectMapper.writeValueAsString(Collections.singletonList(e))

I suspect that I cannot correctly handle the mix of --data and --data-urlencode from example curl in RestTemplate.

Could you please suggest what am I doing wrong?

3 Answers 3

1
  // 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);
Sign up to request clarification or add additional context in comments.

Comments

1

I think the only problem is MediaType, Data which you are sending is not form Data (APPLICATION_FORM_URLENCODED)

It's json data so you need to use MediaType.APPLICATION_JSON Something like this

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

Refer this for more detail on RestTemplate

Comments

0

Works fine for me:

Here is the code with client and request, please ignore request signatures

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'

controller: First request will trigger your code:

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

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

Above request will go to service layer where code is same as of yours.


    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"]>
    }

Then the controller again, just to check whether controller accepts String object or Event object from the caller. Here Event is passed as URLEncodedString, which I am getting here as output.

    @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
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.