I need to consume a vendor API which returns file(.pdf/.jpg/.png) in binary format when request succeeds while returns a JSON Response when Request fails.
The Request method is of type POST.
I tried using below code:
WebClient webClient = WebClient.create();
ResponseEntity<Object> apiResponse = webClient.post()
.uri(new URI("https://api.myapp.in/getDocument"))
.header("mobile", "XXXXXXXXX8")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
//.accept(MediaType.parseMediaType("application/pdf"))
.body(BodyInserters.fromFormData(map))
.retrieve()
.toEntity(Object.class)
.block();
When i execute the above code it works fine and i am able to get the JSON Response for Error case but when the request is success it gives error as below:
Content type 'application/pdf' not supported for bodyType=java.lang.Object
Once your get Response, you can ResponseEntity.getHeaders().
From the response headers you can get the content type and consume your response accordingly.
If API does not return valid content-type based on the response, you can raise a defect on the API provider.
Related
What is the difference with UniRest and Spring RestTemplate which is giving back a 400 Bad Request with apparently the same header and body sent ?
I try to reach the HubSpot API to create a BlogPost, but using RestTemplate I have a 400 Bad Request error, and using UniRest works alright (returns an OK response). However, I do not want to include a library just to make one REST call: I'd rather stick to RestTemplate.
The request data I need to send
HttpMethod: POST
URL: https://api.hubapi.com/content/api/v2/blog-posts?hapikey=*****************
Header: Content-Type: application/json
Body: (represented by a class instance as blogpostSendPost further down)
{
"name": "My first API blog post!",
"content_group_id": 351076997
}
Using RestTemplate
Setting up the request:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<BlogpostSendPost> request = new HttpEntity<>(blogpostSendPost, headers);
log(request.toString());
//LOG PRINT: <BlogpostSendPost(name=My first API blog post!, content_group_id=351076997),[Content-Type:"application/json"]>
OR in JSON
The .json() method converts my object in Json like you can see in the logs
HttpEntity<String> request = new HttpEntity<>(blogpostSendPost.toJson(), headers);
log(request.toString());
//LOG PRINT: <{"name":"My first API blog post!","content_group_id":"351076997"},[Content-Type:"application/json"]>
With .postForObject(): 400 Bad Request
BlogpostResponsePost answer = restTemplate.postForObject(
"https://api.hubapi.com/content/api/v2/blog-posts?hapikey=***********",
request,
BlogpostResponsePost.class);
With .exchange(): 400 Bad Request
BlogpostResponsePost answer = restTemplate.exchange(
"https://api.hubapi.com/content/api/v2/blog-posts?hapikey=**********",
HttpMethod.POST,
request,
BlogpostResponsePost.class);
Using UniRest: OK
HttpResponse<JsonNode> resp = Unirest
.post("https://api.hubapi.com/content/api/v2/blog-posts?hapikey=**********")
.header("Content-Type", "application/json")
.body(blogpostSendPost)
.asJson();
I am using PostMan to call my REST SpringBoot Application which is using theses Services : when I am calling the HubSpot API directly from PostMan it works fine, just like with UniRest lib.
Thanks for your help guys !!
Please refer https://community.hubspot.com/t5/APIs-Integrations/Getting-400-Bad-Request-when-trying-to-add-a-Blog-Post/td-p/306532
Instead of converting request object to json, pass request object directly. It worked for me.
// TRY 1: CONTACTS - RestTemplate - OK - contact is created (API V1)
HttpEntity request1 = new HttpEntity<>(contactSendList, headers);
ContactResponseInformations answer1 = restTemplate
.postForObject(
HubSpotConfiguration.URL_CREATE_CONTACT,
request1,
ContactResponseInformations.class);
log.info(answer1.toString()); // OK
Performing any request, I need to perform Authentication with POST request with body {username:"somename", password:"somepass"},
header Content-Type:application.json which gives me a response with generated token, which I need to paste as a second header, smth like Authorization:generated-tokenkjhsdkjfvjbwjbQ== for further requests.
Could you help me with it, please.
Variant which worked for me:
String token = given()
.contentType("application/json")
.body(new User("someuser" , "123"))
.when()
.post(RestConfig.baseUrl+"/authentication-url")
.then().extract().response().as(TokenResponse.class).getToken();
given()
.contentType("application/json")
.header("Authorization", token)
.get(RestConfig.baseUrl+"/some-path")
.then()
.statusCode(200)...
I had a similar requirement, where I had to pass the auth token back and forth, but this was spring rest template not rest assured. For that purpose, I used client filter, which captured the token on response and set it as a header on request. You can search if there is something similar in rest assured, which can do the job.
Here is a sample, https://github.com/rest-assured/rest-assured/wiki/Usage
Custom Authentication
Rest Assured allows you to create custom authentication providers. You do this by implementing the io.restassured.spi.AuthFilter interface (preferably) and apply it as a filter. For example let's say that your security consists of adding together two headers together in a new header called "AUTH" (this is of course not secure). Then you can do that like this (Java 8 syntax):
given().
filter((requestSpec, responseSpec, ctx) -> {
String header1 = requestSpec.getHeaders().getValue("header1");
String header2 = requestSpec.getHeaders().getValue("header2");
requestSpec.header("AUTH", header1 + header2);
return ctx.next(requestSpec, responseSpec);
}).
when().
get("/customAuth").
then().
statusCode(200);
The reason why you want to use a AuthFilter and not Filter is that AuthFilters are automatically removed when doing given().auth().none(). ...
I could be misunderstanding the question, but from what I am getting from it, I think something like this should work:
String token =
given().
header("Content-Type", "application/json").
body(/* body content goes here */).
when().
post(/* route goes here */).
then().
extract().path("token").toString()
// the above path arg depends on the response you get from the call.
Then the next call would be something like:
given().
header("Content-Type", "application/json").
header("Authorization", token).
when()...etc.
Some of the specifics will depend on the API, but I use this format all the time. Often getting a response of a user ID, or a token, etc. and using it for future calls.
More info on extracting in the rest assured docs: https://github.com/rest-assured/rest-assured/wiki/Usage#extracting-values-from-the-response-after-validation
If you want to extract one parameter from response then this should work:
String jsonBody= ( enter request payload here )
ValidatableResponse response = RestAssured.given().baseUri(baseURL)
.accept("application/json")
.header("Content-Type","application/json")
.body(jsonBody).when().post("/auth")
.then().assertThat().statusCode(200)
.log().all();
String token=response.extract().path("token");
I have GET REST API, which sends some information in response header.
I am writing test case using rest assured framework, issue I am facing is, in response of GET API, I am not getting header string set by the server in rest API response.
I have checked the same API in Rest client and HTTP Resource, there I can see the header information set by server in API response.
But in rest assured Response object, header information set by server is not available.
Rest API code:
#Path("/download")
#GET
#Produces("application/zip")
public Response downloadContractZipFile(#PathParam("contractId") final String contractId) throws CMException{
ContractActionRequest contractActionRequest = new ContractActionRequest();
contractActionRequest.setId(contractId);
DownloadActionResponse downloadActionResponse = (DownloadActionResponse) executeAction(Action.DOWNLOAD, contractActionRequest);
Response res = Response
.ok(downloadActionResponse.getFilestream(), MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition",downloadActionResponse.getContentDisposition())
.header("Expires", "0")
.header("Content-Length", String.valueOf(downloadActionResponse.getContentLength()) )
.build();
return res;
}
Above you can see, API is returning Content-Length in header. But when I am invoking above API using rest assured framework, it does not receive "Content-Length" in header. Assert is getting failed.
Rest assured Test case code:
given().get(propertyURI).then().assertThat().header("Content-Length","7562");
java.lang.AssertionError: Expected header "Content-Length" was not "7562", was "null". Headers are:
X-Powered-By=Servlet/3.0
Cache-Control=no-cache, no-store
Cache-directive=no-cache
Pragma=no-cache
Pragma-Directive=no-cache
Expires=Thu, 01 Jan 1970 00:00:00 GMT
Content-Type=text/html;charset=UTF-8
x-authenticated=false
x-location=https://reena:9453/app/login.jsp?targetApp=OM
Content-Language=en-US
Transfer-Encoding=chunked
I suggest you try Karate instead of REST-Assured as it has much better support for validating response headers.
(disclaimer: am Karate dev)
I am having some issues trying to receive a response message from a Spring RESTful web service to an AngularJS client.
I am using ResponseEntity<String> to return a response to the client. This works when only returning a status code but AngularJS fails with Unexpected token R when I send a response message in the body.
What am I doing wrong?
return new ResponseEntity<String>(HttpStatus.OK);
But this does not work:
return new ResponseEntity<String>("Report was updated successfully", HttpStatus.OK);
AngularJs code:
$http.get(url, header)
.success(function(data, status, headers, config) {
// some logic
}).error(function(resp, status) {
// some logic
});
Response:
Is Angular expecting JSON or HTML/text back?
I've experienced issues in the past returning text/javascript or application/json instead of text/html. It looks like Angular is expecting JSON or JSONP in that instance, hence the Unexpected Token R (which is the first letter of your response string).
I could give a more precise answer, but I'd need to also know if you're using JSONP vs JSON, etc.
I am using Restful web Service using Dropwizard. And generating response as:
Response response = resources.client().resource("/url")
.header("CONTENT-TYPE","value")
.post(Response.class, jsonRequestString);
Now I want to write unit test to ensure the returned content type is corrected in Response Object. how to do that?
You can use the ClientResponse type in Jackson. For example, using a GET operation:
ClientResponse response = Client.create()
.resource(url)
.get(ClientResponse.class);
String contentType = response.getHeaders()
.getFirst("Content-Type");
System.out.println(contentType);