How to POST XML string using RestTemplate - java

I have the following scenario. I have an XML file:
query-users.xml
<?xml version="1.0"?>
<q:query xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3">
</q:query>
When executing the curl commend:
curl.exe --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST http://localhost:8080/midpoint/ws/rest/users/search -d #C:\Users\user\query-users.xml
I get the desired response in XML.
I am trying to do the same POST request using RestTemplate from JAVA code:
try{
StringBuilder builder = new StringBuilder();
builder.append("http://localhost:8080/midpoint/ws/rest/users/search");
builder.append("?query=");
builder.append(URLEncoder.encode("<?xml version=\"1.0\"?><q:query xmlns:q=\"http://prism.evolveum.com/xml/ns/public/query-3\"></q:query>"));
URI uri = URI.create(builder.toString());
restOperations.postForEntity(uri, new HttpEntity<String>(createHeaders("username", "pass")), String.class);
logger.info(response);
}catch(Exception e){
logger.info(e.getMessage());
}
}
I get Internal Servel Error .
There is something that I am doing wrong passing the XML string to the POST request with RestTemplate, but I am not figuring out what it is.
Is there a way how to solve this?
Thanks

Your curl invocation and RestTemplate call are not equivalent. In first one you pass your xml as a a body of HTTP Request (this is what -d option does). In your RestTemplate you assign your xml to query and consequently HTTP Request has no payload and your data is encoded in URL.
If you want to pass your xml as a HTTP Body, you should use different HttpEntity constuctor: http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpEntity.html#HttpEntity-T-org.springframework.util.MultiValueMap-

Related

Specify Content-Type in form-data part as application/json

I am creating a multipart RequestBody using OkHttp3. The following is the working curl request.
curl --location --request POST 'https://<url>' --form 'object=#<file_path>' --form 'config={"access":"YES"};type=application/json'
Removing ;type=application/json, produces an error from our Spring Boot server.
Content type 'application/octet-stream' not supported.
So it is clear that I should specify Json type for config. Let's create the Request using OkHttp.
String mimeType = URLConnection.getFileNameMap().getContentTypeFor(file.getName());
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart(
"object", filename,
RequestBody.create(MediaType.parse(mimeType), file)
)
.addFormDataPart("config", "{\"access\":\"YES\"}") // CAN'T FIND A WORKING OPTION TO SPECIFY CONTENT TYPE HERE.
.build();
This produced the same error as mentioned above. So I changed the code as follows.
.addPart(
Headers.of("Content-Type", "application/json"),
RequestBody.create(MediaType.parse("application/json"), "{\"access\":\"YES\"}")
)
Now the OkHttp request builder throws this error.
Unexpected header: Content-Type
Using an empty header Headers.of(), creates the request body, but then I realized the form-data key config is not specified, from this API error.
Required request part 'config' is not present
I searched a lot, but can't find any solution with OkHttp, I found solutions in other libraries such as Spring RestTemplate.
This might work too.
.addFormDataPart(
"config",
null,
RequestBody.create(MediaType.parse("application/json"), "{\"access\":\"YES\"}")
)
After playing with this code, I got a way to specify the Content-Type.
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"config\""),
RequestBody.create(MediaType.parse("application/json"), "{\"access\":\"YES\"}")
)

Post call for file upload not working as expected using java

Post call for file upload not working as expected using java.I need to upload a file using rest call..The file format is correct and its working perfectly in postman and ui side also but in java its giving "Incorrect file format" as the file is not getting uploaded it seems. Am i missing any header or anything.
File file = new File("/Users/surya/Downloads/2021-06-16.xlsx");
Response response = RestAssured
.given()
.multiPart("file", file, "multipart/form-data")
.post("http://myuploadsite.com/upload/feedfile");
System.out.println(response.asString());
My postman curl request
curl --location --request POST 'http://myuploadsite.com/upload/feedfile' \
--header 'Content-Type: multipart/form-data; boundary=jena' \
--header 'Host;' \
--form 'file=#"/Users/surya/Downloads/2021-06-16.xlsx"'
Method you're using is:
RequestSpecification multiPart(String controlName, File file, String mimeType);
You need to define mimeType for file you're uploading, in this case is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet or application/vnd.ms-excel. I'm not quite sure which one.
or just leave blank to use overload method:
RequestSpecification multiPart(String controlName, File file);
Code would be:
File file = new File("/Users/surya/Downloads/2021-06-16.xlsx");
Response response = RestAssured
.given()
.multiPart("file", file, "application/vnd.ms-excel")
.post("http://myuploadsite.com/upload/feedfile");
System.out.println(response.asString());
Content-Type: multipart/form-data will be automatically defined by Rest-Assured when you use multipart
https://github.com/rest-assured/rest-assured/wiki/Usage#multi-part-form-data

How to use RestTemplate to make a POST call with a request body

I'm trying to make a POST request using RestTemplate to send a request body and headers.
To do this, I saw that many are using HTTPEntity class. But this class a generic type which needs to be passed. The content type is application/json.
In most cases, I saw that HttpEntity was created with String generic type. Like this:
HttpEntity<String> requestEntity = new HttpEntity<String>(body, headers);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
What I didn't get is, how do I know which data type to use while creating HttpEntity object?
I understood that we do ResponseEntity parse the response from the http call into a string. But I didn't understand the same for http entity.
I tried to create the body in http entity object using google's JsonObject, like this:
JsonObject body = new JsonObject();
body.addProperty("key", "value");
.....
The request when tried in postman works, but didn't work in code using RestTemplate when I used String http entity.
When using JsonObject type, I'm getting this error:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Not a JSON Primitive
When using String type http entity, I'm getting some generic error message saying the request isn't valid.
Adding the complete request body :
JsonObject body = new JsonObject();
body.addProperty("transaction_id", transaction_id);
body.addProperty("timestamp", timestamp);
body.addProperty("device_token", deviceToken);
if (forUpdate)
body.addProperty("bit0", true);
The working curl from postman:
curl -X POST \
https://api.devicecheck.apple.com/v1/query_two_bits \
-H 'Content-Type: application/json' \
-H 'authorization: Bearer SOME_BEARER_TOKEN_STRING' \
-H 'cache-control: no-cache' \
-d '{
"device_token": "SOME_DEVICE_TOKEN",
"transaction_id": "f0bc2e5d-5bd9-4437-a455-fd1e210a6268",
"timestamp": 1557073737608
}'
So can someone please help me in understanding how to send this request?

How can I send a body in a HTTP request using Apache http client's URIBuilder?

I know I can add http parameters using the setParameter method, but how do I pass a body to the http request using the URIBuilder class?
For example, this
URI uri = new URIBuilder().setScheme("http")
.setHost("localhost:9091/test").setParameter("a", "1")
.setParameter("b", "2").build();
is equivalent to the following curl request:
curl -X POST http://localhost:9091/test\?a\=1\&b\=2
but how do I build a URL using URIBuilder (or any other class) for the following curl:
curl -X POST http://localhost:9091/test -d '{"a":1,"b":2}'
HttpUriRequest request = RequestBuilder.create("POST")
.setUri("http://localhost:9091/test")
.setEntity(new StringEntity("{\"a\":1,\"b\":2}", ContentType.APPLICATION_JSON))
.build();

MockMvc show corresponding curl command or http request

I have a line of code that performs a request to an API but I can't figure out the exact format of the request.
mapper.writeValueAsString from here.
mockMvc from here.
mockMvc.perform(post("/press/group").param("filterId", filterId).content(mapper.writeValueAsString(someObject)).contentType(MediaType.APPLICATION_JSON))
I'm trying to convert the code to Python and if there's a way to have my mockMvc output the corresponding HTML request it would be very helpful. The API I'm querying lacks documentation
Thanks and any guidance is much appreciated
MockMvc allows you to print both the request and the response.
In your case, you should do:
mockMvc.perform(post("/press/group").param("filterId", filterId).content(mapper.writeValueAsString(someObject)).contentType(MediaType.APPLICATION_JSON)).andDo(print());
This will print the output to the console, and it will look something like this:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /press/group
Parameters = {filterId=[filterId_val]}
Headers = {}
Handler:
Type = com.yourCompany.yourController
Method = public ReturnType com.yourCompany.yourController.yourHandlerMethod(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body = {"val1" : "val_one"}
Forwarded URL = null
Redirected URL = null
Cookies = []
This should be enough info for you to construct the http request in python.
Don't know about mockMVC, but if this gets rendered in an HTML page, you could use the Chrome developer tools to generate the curl statement for you.
Start Tools/Developer Tools, click the network tab, click the link/button/thing that causes the request, find the request in the Network tab, right click, copy as cUrl.
Obviously, if it's not rendered in an HTML page, this isn't going to be a great deal of help.
Extract value of string of mapper.writeValueAsString(someObject)
this string is JSON (MediaType.APPLICATION_JSON) so it should look like:
{"attribute":"value","attribute":"value"}
And param("filterId", filterId)
is added to your url (variable filterId is some string so extract it)
/press/group?filterId:filterIdString
Paste it to the curl message:
curl -X POST -d '{"attribute":"value","attribute":"value"}' -H "Content-Type: application/json" "admin:password#localhost:8080/press/group?filterId:filterId" -i
Look at response
Explanation
X type of request
-d data
-H content type
admin:passwor# credentials
-i informations

Categories

Resources