Http 400 using resttemplate postforobject - spring-boot

Below is the code which gives 400 bad request, tried various options with this but always ends up with 400 bad request, however the same works using OkHttp client
HttpHeaders hh = new HttpHeaders();
RestTemplate rt = new RestTemplate();
String reqBody = new ObjectMapper.writeValueAsString(“test msg”);
headers.set(“Accept”, “text/plain”);
headers.set(“content-type”,”application/json”);
headers.set(“authorization”, “Basic xxxxx”);
headers.set(“ibm-mq-rest-csrf-token”,”blank”);
HttpEntity<String> request = new HttpEntity<>(reqBody.toString());
ResponseEntity<Object> result = rt.postForObject(url, request, Object.class);
Below code works using okhttp

Your content does not appear to be JSON, in both cases it appears to be plain text. Therefore the header
Content-Type: text/plain
should be used rather than
Content-Type: application/json
I am unsure why this works in your OKHTTP example, unless perhaps the media type you use to build your post body somehow over-rides your Content-Type header?

Related

Get response body in response 400 HTTP Rest Template

I'm using Rest template to make a request to a service. But I'm getting response code 400 and response null. I made the same call by postman, with the same parameters and I'm getting the body response. How do I get the body response?
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("Authorization", "Bearer " + token);
headers.add("kms_credencial", parametros.get("KMS_CREDENCIAL"));
headers.add("kms_credencial_tipo", parametros.get("KMS_CREDENCIAL_TIPO"));
HttpEntity<MultiValueMap<String,Object>> entity =
new HttpEntity<MultiValueMap<String, Object>>(request, headers);
ResponseEntity<String> response = null;
response = restTemplate.exchange(parametros.get("SERVICE_HUB2_BASE_URL") + "/fw/v1/pdf/kms/lote/assinaturas",
HttpMethod.POST, entity, String.class);
Could someone tell me what's wrong?
I had the same problem.
From what I've seen, ResteTemplate doesn't accept an error response (400, 500) with a 'large' body.
I still haven't found a solution, but I'm studying the parameters that the method accepts to see if any of them allows receiving a larger body

sending GET request via REST template with JSON request body getting failed with binding binding element must be a struct error?

I am trying to send a GET request using REST Template with a JSON request body, but the request is failing with error,
processing
failedorg.springframework.web.client.HttpServerErrorException$InternalServerError:
500 Internal Server Error: [code=400, message=binding element must be
a struct]
I have tried hitting the endpoint using the insomnia and the request is going through successfully, There I have put 2 headers
1. Content-Type - application/json
2. Authorization - Bearer ******
And the JSON body.
My code in spring boot looks like this.
ResponseEntity<String> responseObject = null;
String URL = "https://myurl/endpoint";
String requestBody = "{\"requestType\":\"status\"}";
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization","Bearer ***");
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity httpEntity = new HttpEntity<>(body,headers);
System.out.println(httpEntity+" httpEntity");
System.out.println(headers+" headers");
responseObject = restTemplate.exchange(URL, HttpMethod.GET, httpEntity, String.class);
The sout for httpentity and header looks like this
httpEntity
<{"requestType":"status"},[Authorization:"Bearer *******************", Content-Type:"application/json"]>
headers
[Authorization:"Bearer *************************", Content-Type:"application/json"]
Also when I am trying to send a request without the body to another endpoint using rest template, that is getting executed successfully, so I think something with the way I am sending the body has to do with the error.
rest template doesn't support get request with body . for more details you can refer this article.
If you are on Java 11 I would suggest you to use java.net.HttpClient which will fulfill your need.

how to handle "Transfer-Encoding=chunked" in SI HttpRequestExecutingMessageHandler

I am calling an external server using HttpRequestExecutingMessageHandler. I am using a JSON to object transformer to convert the JSON data. But I am getting the following exception.
Caused by: com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (String)"�
when I checked the headers I found the following.
Transfer-Encoding=chunked
Is this the reason for the exception log?
The outbound gateway and JsonToObjectTransformer are given below:
#ServiceActivator(inputChannel = "channelOutboundRequest")
#Bean
public HttpRequestExecutingMessageHandler outboundGateway() {
final HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(
endpoint);
handler.setExpectedResponseType(String.class);
handler.setHttpMethod(HttpMethod.POST);
handler.setOutputChannelName("channelResponse");
handler.setAdviceChain(Collections.singletonList(advice()));
return handler;
}
#Bean
#Transformer(inputChannel = "channelResponse", outputChannel = "channelReply")
public JsonToObjectTransformer transformer(ObjectMapper objectMapper) {
final JsonObjectMapper<?, ?> mapper = new Jackson2JsonObjectMapper(objectMapper);
return new JsonToObjectTransformer(DetailsDTO.class, mapper);
}
If the header is causing the issue, how can I handle the response?
Note: If I hit the external server directly using postman, I am getting the response in JSON structure.
I have no idea what's wrong here.. If I use the simple restemplate call like below, it works properly.
JSONObject jsonObject = new JSONObject("{\"code\":\"F001\",\"transactionId\":\"1008566223232\"}");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth("token");
HttpEntity<String> request =
new HttpEntity<String>(jsonObject.toString(), headers);
String respns = restTemplt.postForObject("http://endpoint", request, String.class);
System.out.println(respns);
JSONObject response = new JSONObject(respns);
One difference I could find was in the response headers. those are given below:
Outbound gateway response headers :-
{Transfer-Encoding=chunked, http_requestMethod=GET, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#d8b195e, Server=nginx, Accept=/, Connection=keep-alive, User-Agent=PostmanRuntime/7.28.0, Host=localhost:8901, Accept-Encoding=gzip, deflate, br, http_statusCode=200 OK, Date=1622533072000, Authorization=Bearer token, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#d8b195e, Cache-Control=no-cache, ETag=W/"1009-5SzdL+uWyY6ZcMWht5dMtm2Sxlc", Content-Encoding=gzip, http_requestUrl=http://inboundurl, id=be07fc8d-d478-5fa9-33e4-61a2b5f92468, Content-Length=207, contentType=application/json;charset=utf-8, Content-Type=application/json, requestFrom=CUSTOM_HEADER, timestamp=1622533092827}
Normal restTemplate call response header
[Server:"nginx", Date:"Tue, 01 Jun 2021 07:34:54 GMT", Content-Type:"application/json; charset=utf-8", Content-Length:"4105", Connection:"keep-alive", Access-Control-Allow-Origin:"*", Content-Security-Policy:"default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests", X-DNS-Prefetch-Control:"off", Expect-CT:"max-age=0", X-Frame-Options:"SAMEORIGIN", Strict-Transport-Security:"max-age=15552000; includeSubDomains", X-Download-Options:"noopen", X-Content-Type-Options:"nosniff", X-Permitted-Cross-Domain-Policies:"none", Referrer-Policy:"no-referrer", X-XSS-Protection:"0", ETag:"W/"1009-llD9DqxYkEsjyikWajYk+16cb1k""]
Can anyone please help?
After many trials and errors, I found the reason for this. Accept-Encoding=gzip, deflate, br this header in the outbound gateway request is the root cause. the response I am getting is a long string and it is getting compressed because of this header. i added a header filter before the outbound gateway to remove this header.
#Bean
#Transformer(inputChannel = "channelHeaderFilterReq", outputChannel = "channelHeaderFilterRes")
public HeaderFilter filter() {
return new HeaderFilter("Accept-Encoding");
}
Now everything works fine..!!

How to remove and add new Accept header to Spring boot Rest Template?

I'm consuming a GraphQL Service, it is returning 406 Not Acceptable if the Accept header is text/plain.
It is expecting to Accept as application/json
So I tried override the RestTeamplate Headers. However it seems the Accept header test/plain is always present there. I confirmed this by enabling debug(logging.level.org.springframework.web.client.RestTemplate=DEBUG)
Console
o.s.web.client.RestTemplate: Accept=[text/plain, application/json, application/*+json, */*]
o.s.web.client.RestTemplate: Writing [{products(query: "title:tow*", first: 10) {edges {node {id legacyResourceId title}}}}] as "application/graphql"
Here is the code I tried to override the Accept header
HttpHeaders headers = new HttpHeaders();
RestTemplate restTemplate = new RestTemplate();
headers.add("Content-Type","application/graphql");
headers.setAccept(Collections.singletonList(new MediaType("application","json")));
String content = "{products(query: \"title:tow*\", first: 10) {edges {node {id title}}}}";
HttpEntity<String> requestEntity = new HttpEntity<String>(content, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
I even tried removing the Accept header first(headers.remove("Accept")) and then setAccept but still it doesn't remove it from the log.
Is there anything else need to be done?
Why is it not removing the text/plain from the Accept header?
Why I see multiple options in Accept when I set only one option?

Invalid mimetype exception in Spring boot rest call

I am new to both Spring boot and rest calls.
I am trying to consume a rest service and I do not have any information about that rest API except URL. When I hit that URL from a browser I am getting a response as {key:value}. So, I assumed that it is a JSON response.
I am consuming it in spring boot as follows
restTemplate.getForObject(url, String.class) .
This is giving Invalid mime type "content-type: text/plain; charset=ISO-8859-1": Invalid token character ':' in token "content-type: text"
I assume that this error is because response content type is set to text/plain but it is returning JSON format.
EDIT:
Tried this way but did not work.
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters",headers);
ResponseEntity<String> result = restTemplate.exchange(url,HttpMethod.GET,
entity, String.class);
How to handle and solve it?
You might want to read about the request headers your REST API needs. Content-Type header specifies the media type of the request you're sending to the server. Because you're just getting data from the server you should set the Accept header to the kind of response you want i.e., Accept: application/json.
Unfortunately, you can't set headers using getForObject(). You could try this:
URL url = new URL("Enter the URL of the REST endpoint");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer content = new StringBuffer();
String inputLine;
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
}

Resources