Post multipart file and JSON in Rest Assured - java

I need to send a video file and JSON object in Rest Assured post call.
Structure is like the following:
{ "sample" : {
"name" : "sample-name",
"kind" : "upload",
"video_file" : multipart file here } }
So I did like the following
Code:
given()
.header("Accept", "application/json")
.header(auth)
.config(rConfig)
.body(body)
.multiPart("sample[video_file]", new File("path"), "video/mp4")
.formParam("sample[name]", "Video Upload")
.formParam("sample[kind]", "upload")
.log().all().
expect()
.statusCode(expectedStatusCode)
.post(url);
I can't use application/JSON while using multipart in Rest Assured. I explicitly hardcoded the value in the form param and sent the media file in multipart and now it is working fine.
How can I send all the form param data in a single inner object.

You can do this by using RequestSpecBuilder. It supports all the request parameters and you can easily create multipart request.
Sample code taken from https://github.com/rest-assured/rest-assured/wiki/Usage
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.addParam("parameter1", "parameterValue");
builder.addHeader("header1", "headerValue");
RequestSpecification requestSpec = builder.build();
given().
spec(requestSpec).
param("parameter2", "paramValue").
when().
get("/something").
then().
body("x.y.z", equalTo("something"));

Thanks for your response rohit. I was post this question for handling inner object with formParams. I've completed by creating a Hash Map for formParams. Because formParams method of rest assured can accept Hash map.
Form params map creation:
private static Map<String, String> createFormParamsMap(VideoTagInput videoTag) {
Map<String, String> formParams = new HashMap<>();
formParams.put(createFormParamKey("name"), "name");
formParams.put(createFormParamKey("kind"), "kind");
return formParams;
}
private static String createFormParamKey(String paramKey) {
return "sample[" + paramKey + "]";
// output is like "sample[name]" - I'm forming inner object here for my purpose.
}
Finally send the map to Rest Assured post call function
given()
.header("Accept", "application/json")
.header(auth)
.config(rConfig)
.multiPart("sample[video_file]", new File("path"), "video/mp4")
.formParams(requestParamsMap) // requestParamsMap here.
.log().all().
expect()
.statusCode(expectedStatusCode)
.post(url);

Your approach is definitely not standard.
You cannot have a multipart request and a JSON body, you need to pick one over the 2 approaches: multipart/form-data or application/json request.
The standard way is to have a multipart request with a "json" param containing the serialized JSON payload, and a "file" param with the multipart file.
given()
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
.multiPart(file)
.param("json", "{\"sample\":{\"name\":\"sample- name\",\"kind\":\"upload\",\"video_file\":<this is not needed>}}")
But this involves changing your server-side logic.
If you cannot change your server-side logic, you need to serialize your file as (for instance as an array of bytes, or as base64 string) to be set as video_file in your JSON payload. In which case you'll have an application/json content type request, not a 'multipart/form-data'.

Related

How do I return Http Response Content Length for ResponseEntity<List<Object>> without formatting issues or losing data from my response body?

I'm trying to set the content length of my ResponseEntity<List> but the full list isn't returned in the response. I tried something like
long contentLength = staticMethodGetsContentLength(List<Object> objectList);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Length", String.valueOf(contentLength));
return Response.ok().headers(headers).body(objectList);
and then what is returned is a JSON list like
[
{
"data": "data"
without closing brackets or the full list of objects. Is there an easy fix for this or an alternative to what I'm doing?

HttpRequest.BodyPublishers.ofString(jsonasstring) does not put anything in the POST request

I'm trying to make a POST request with custom headers and json as string on body
Here's my code
HttpRequest request2 = HttpRequest.newBuilder()
.uri(URI.create(POSTS_API_URL))
.headers("accept", "text/plain; charset=UTF-8", "XF-Api-Key", "MYAPIKEY")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
System.out.println(request2); //result : https://******.fr/api/auth/ POST
System.out.println(request2.headers()); //result : java.net.http.HttpHeaders#8e33ff08 { {accept=[text/plain; charset=UTF-8], XF-Api-Key=[MYAPIKEY]} }
HttpResponse<String> response2 = client.send(request2, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response2.statusCode()); //400
// print json code
System.out.println(json); //{"login":"LunaLune","password":"***********"}
// print response body
System.out.println(response2.body()); //mandatory input missing : login, password
And my json String
String json = "{" +
"\"login\":\"LunaLune\"," +
"\"password\":\"*********\"" +
"}";
But when I print the request I get : https://*******.fr/api/auth/ POST
the POST request is empty
I googled many forums, code examples ect... but I see that my code where correct according many examples I seen.
So if someone know what is my problem ?
Thanks in advance !
You need to set "Content-Type" as "application/json" in the request header.
See: Which JSON content type do I use?

Spring RestTemplate get raw json

I am using spring restTemplate to consume some rest service which gives me json response. My problem is that when I get the response, it consists of all weird characters instead of simple json response which server is providing. Initially I thought its simple charcter encoding problem but even after setting correct converters I am getting problem. My code -
RestTemplate restTemplate1 = new RestTemplate();
restTemplate1.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
responseEntity = restTemplate1.exchange(uri, request.getMethod(),
new HttpEntity<String>(body, requestHeaders), String.class);
Request headers are created as follows -
private MultiValueMap<String, String> getHeadersInfo(HttpServletRequest request) {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.put("Accept", Arrays.asList("text/plain, text/plain, application/json, application/*+json, */*, */*"));
map.put("Content-Type", Arrays.asList("application/json; charset=UTF-8"));
return map;
}
Also, if I use getForObject instead of exchange method (as following), then I get the correct result but I can't use this as I need to add some headers.
String a = restTemplate.getForObject(uri, String.class);
I have checked many blogs and stackoverflow questions but they all have suggested the techniques which I have already tried here.
Any suggestions?
Type of response I am getting -
???Oo7???x???4?K\???[?Ð??H??v? ??K?????^\?y???/M???vw???Y?0?6???U???Q????????K?=N{?rZ??n-??8????-?l????????7C?l?????~"???a???Z????U3???3?9???)?J?+???n???d?????? ???\??\o?????? ?????????n????t??2` ???8KLK?R?IJ1????t?\k?û?????j??^#???n??????{??aUV?g\?Q???p? ?V?z???w?R?????? >(IsL,?)?&?TH??.+/LU?Eq??????)??m????n??,4?9hn?{?f18??Z?jW ??5x?JOH%#0$?"?-Ra/??QA;.??*fN#?U?(?????~????s???#??X=W?l?????????Y?T??AR?R???WC=?L^A"t$?R4]J?m]M]???J??my ??ic?,;7OH??}?????'^J????????"'?R????X?X???&???"?`?2^y?-?? i???M??A??ljWu?/|!?qs?v{i?N?'?r?L??3???e??PNV'-.? SN?Y?????:d[#?]?????Wg?,???????????vdq6e?????#Yb??=pM??#<)$ ?8W\???ItQ?P/?R??P?7????:???

Create a reusable method to build POST call to accept more than 1 headers

I have a post method to accept 4 parameters.
RequestBody body = RequestBody.create(type, postData);
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", ssid)
.post(body)
.build();
But few of my calls have more than one header. I can take care of passing the values through a context map. But, how can I build the request in a manner to accept multiple header values.
Example, the above code accepts authorization header.
Another call has two more headers tag1, tag2. the method should be able to tell that 2 sets of values have been passed to it and should build the request accordingly. Is it posssible?
You don't have to build the result immediately. You can store the result of Request.Builder() in a variable, loop over your headers, and add them to the builder. This is one of the positives of using a builder instead of a constructor because up until the point that you call build(), you can keep modifying what will be built using whatever loops or function you would like to use to modify the builder.
public static Request requestWithHeaders(String url, RequestBody body, List<String> headerNames, List<String> headerValues) {
if (headerNames.size() != headerValues.size()) {
throw new IllegalArgumentException(String.format(
"Must provide the same number of header names and header values. "
+ "%d header names and %d header values provided",
headerNames.size(),
headerValues.size()));
}
Request.Builder builder = new Request.Builder()
.url(url)
.post(body);
for (int i = 0; i < headerNames.size(); ++i) {
builder.addHeader(headerNames.get(i), headerValues.get(i));
}
return builder.build();
}
You can then call it like this for instance:
Request request = requestWithManyHeaders(
url,
body,
Arrays.asList("auth", "tag1", "tag2"),
Arrays.asList("authValue", "tag1Value", "tag2Value")
);

Java : How to handle POST request without form?

I'm sending a http post request from javascript, with some json data.
Javascript
var data = {text : "I neeed to store this string in database"}
var xhr= new XMLHttpRequest();
xhr.open("POST","http://localhost:9000/postJson" , true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(data);
xhr.setRequestHeader("Connection", "close");
//Also, I've tried a jquery POST
//$.post('postJson', {'data=' : JSON.stringify(data)});
//But this doesn't make a request at all. What am I messing up here?
Route
POST /postJson controllers.Application.postJson()
Controller
public static Result postJson(){
//What should I write here to get the data
//I've tried the below but values is showing null
RequestBody rb=request().body();
final Map<String,String[]> values=rb.asFormUrlEncoded();
}
What is the way to parse the POST request body?
Much thanks!
Retreive the request body directly as JSON... no need to complicate your life.
public static Result postJson() {
JsonNode rb = request().body().asJson();
//manipulate the result
String textForDBInsertion = rb.get("text").asText(); //retreives the value for the text key as String
Logger.debug("text for insertion: " + textForDBInsertion
+ "JSON from request: " + rb);
return ok(rb);
}
Also, I recommend you use the AdvancedRestClient Chrome plugin for testing. This way you can eliminate from the equation client-side code errors.
Cheers!

Categories