Rest-assured POST call with multipart that contains Vietnamese characters in contentbody - java

I am sending POST call to an endpoint with a controlname's contentbody that contain Vietnamese character (such as á ư, ồ, ự..).
Although request was sent successfully, those special characters were replaced by ??? like ch?a ???c n? where it should be chưa được nè at UI :
public class MakeCostObject {
RequestSpecBuilder requestSpec;
public MakeCostObject() {
requestSpec = new RequestSpecBuilder();
String note = "chưa được nè";
String status = "init";
requestSpec.addMultiPart("note", note);
requestSpec.addMultiPart("status", status);
}
public RequestSpecification createCost() {
public RequestSpecification createCost () {
return requestSpec.build();
}
}
}
This is POST request, spec is created from createCost function.
response = given()
.header("Content-type", "multipart/form-data")
.header("Authorization", token)
.when()
.spec(spec)
.post(APIPath.apiPath.POST_cost_upload);
response.then().assertThat().statusCode(201);
I tried another API (non form-data), and UI can display perfectly.
String str = "Tiếng việt";
Map<String, Object> body = new HashMap<>();
body.put("note", str);
given().spec(HeaderConfigs.headerwithnewToken())
.when()
.body(body)
.patch("/costdetail/xxxx/");
How can I config to encode or something to solve my issue?
My io.rest-assured version : 4.2.0.
Thanks.

I have solved the issue by myself. Just replace:
requestSpec.addMultiPart("note", note);
by
requestSpec.addMultiPart(new MultiPartSpecBuilder(note).controlName("note").charset(Charsets.UTF_8).build());

Related

How to extract accesss token value from one API response body(in one class) into another API header(in another class) in rest assured code

Have one token generation API in one class which gives the below response.
{
"access_token": "eyJraWQiOiJNR2FOQUtYXC9pa0grNE1wTE9aS05wMGtqbXNOd0lzXC9WXC9EYm1LZ0pZdTZNPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIxYjBtcjc4cHNjMHIyM25nYnJqMml1MnNkNCIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoic2dwZi5wcm9kdWN0XC",
"expires_in": 3600,
"token_type": "Bearer"
}
Then have another Get API in another class in which I want to extract this access_token value in the header in rest assured code. So how can I take that access token value in another class?
public class Get_Service_List {
private Response response;
String BaseUrl = "https://dev.api.sgf.eus.nt/pro";
#Given("Get Service list API")
public void get_Service_list_API() {
RestAssured.baseURI = BaseUrl;
}
#When("call the API with valid token and details")
public void call_the_API_with_valid_token_and_details() {
response = RestAssured.given()
.header("Content-Type", "application/json")
.header("Authorization", "Bearer "+TokenGeneration.accessToken)
.when()
.get("/api/protsvc/ser");
}
#Then("validate the resonse body with list of services")
public void validate_the_resonse_body_with_list_of_services() {
String response_body = response.getBody().asString();
System.out.println("response is: " +response_body);
}
#Then("validate for 200 status code")
public void validate_for_status_code() {
int status_code = response.getStatusCode();
System.out.println("status is: " +status_code);
}
}
I don't know much about how cucumber share state. Below is the way to extract access_token from response.
String accessToken = response.jsonPath().getString("access_token");

Authorization Bearer token is not included for request

I am trying to run my autotests with serenity and rest-assured, but the token is not included in my request generation method. The method of getting the token itself works correctly. tell me what could be the reason.
public class ApiSteps {
private String token;
public String getAccessToken() {
RequestSpecification requestSpec = RestAssured.with();
requestSpec.given().contentType("application/x-www-form-urlencoded");
Response giveToken = RestAssured.given()
.formParam("username", "user")
.formParam("password", "pass")
.request().post("https://test.com/token");
DocumentContext doc = JsonPath.parse(giveToken.asString());
token = doc.read("access_token");
System.out.println(token);
return token;
}
final RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri("https://test.com/api/v1")
.addHeader("Content-Type","application/json")
.addHeader("Accept", "text/plain")
.addHeader("Authorization", "Bearer " + getAccessToken())
.build();
#Step
public void testRest() {
given()
.spec(spec)
.when()
.get("/Test")
.then()
.assertThat()
.statusCode(200);
}
}
when starting a test in a request - null. I tried to mark with the annotation #Before, but the result is the same
You need to move the method for getting the token into a separate class and use it as follows:
NameClass nameClass = new NameClass();
.addHeader("Authorization", "Bearer " + getAccessToken())
and here use the method of this class:
nameClass.getAccessToken()

Retrofit2 FromUrlEncoded not handling Japanese characters

When sending POST requests to an API endpoint using #FormUrlEncoded from RetroFit2, the record looked scrambled when it was Japanese but ok when English.
The charset was set to null when using to send POST request.
Content-Type:application/x-www-form-urlencoded was the header instead of Content-Type:application/x-www-form-urlencoded; charset=utf-8
#FormUrlEncoded
#POST("/api/items")
Call<ApiResponse> post(#FieldMap Map<String, Object> fields);
2 Solutions:
add the headers manually for each endpoint, not very scaleable solution
#FormUrlEncoded
#POST("/api/items")
#Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8")
Call<ApiResponse> post(#FieldMap Map<String, Object> fields);
add an interceptor to add it for endpoints having POST, a bit more verbose:
#Bean
public ApiService apiService(final ObjectMapper objectMapper) {
final OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(chain -> {
final Request original = chain.request();
if (original.method().equals("POST")) {
final Buffer buffer = new Buffer();
original.body().writeTo(buffer);
final String content = buffer.readString(StandardCharsets.UTF_8);
final RequestBody body = RequestBody.create(MediaType.parse(""application/x-www-form-urlencoded"), content);
final Request request = original.newBuilder().method(original.method(), body).build();
return chain.proceed(request);
} else {
return chain.proceed(original);
}
}).build();
final Retrofit retrofit = new Retrofit.Builder()
.client(httpClient)
.baseUrl(apiBaseUrl)
.build();
return retrofit.create(ApiService.class);
}

How to do GET API Request with URL params?

Client client = ClientBuilder.newClient();
urlApi="https://localhost:123/demo/api/v1/rows/search?";
WebTarget webTarget = client.target(urlApi);
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
webTarget.queryParam(entry.getKey(), entry.getValue());
}
webTarget.queryParam("searchConditions",webTarget.queryParam("mobileNo","+9999999999"));
Invocation.Builder builder = webTarget.request();
builder.header("id", "ABC");
String asB64 = Base64.getEncoder().encodeToString("ABC:PWD".getBytes("utf-8"));
logger.debug("Calling API "+urlApi);
builder.header("Authorization", "Basic "+asB64);
builder.header("Content-type", MediaType.APPLICATION_JSON);
response = builder.get();
responseData = response.readEntity(String.class);
System.out.println(responseData);
I am trying to do GET request with searchCondition as Key and value as {mobileNo="+919999999999"}, I am unable to get this to work.
Apart from that, how can I print the Request "Headers" along with "Query params"? Thank you in advance
I think you need to encode the value inputs, something like this:
webTarget.queryParam("searchCondition", URLEncoder.encode("{mobileNo=\"+919999999999\"}", StandardCharsets.UTF_8.toString()));
UDPATE:
Example of the rest client with Spring:
#Test
public void testStack() throws Exception {
RestTemplate rest = new RestTemplate();
String fooResourceUrl="http://localhost:8080/usersParam?";
RestTemplate restTemplate = new RestTemplate();
String parameter = "{mobileNo=\"+919999999999\"}";
ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "parameter=" + URLEncoder.encode(parameter, StandardCharsets.UTF_8.toString() ), String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
And this would be the rest service:
#RequestMapping(method = RequestMethod.GET, value="/usersParam")
public User getUsersInfo(#RequestParam String parameter) throws UnsupportedEncodingException {
System.out.println(URLDecoder.decode(parameter, StandardCharsets.UTF_8.toString() ));
return null;
}

Get STRING response from restTemplate.put

I'm having a problem using Spring restTemplate.
For now i'm sending a PUT request for a restful service and that restful service send me back important informations in response.
The question is that restTemplate.put are a void method and not a string so i can't see that response.
Following some answers i've change my method and now i'm using restTemplate.exchange, here are my method:
public String confirmAppointment(String clientMail, String appId)
{
String myJsonString = doLogin();
Response r = new Gson().fromJson(myJsonString, Response.class);
// MultiValueMap<String, String> map;
// map = new LinkedMultiValueMap<String, String>();
// JSONObject json;
// json = new JSONObject();
// json.put("status","1");
// map.add("data",json.toString());
String url = getApiUrl() + "company/" + getCompanyId() + "/appointment/" + appId + "?session_token=" + r.data.session_token;
String jsonp = "{\"data\":[{\"status\":\"1\"}]}";
RestTemplate rest = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("Accept", "*/*");
HttpEntity<String> requestEntity = new HttpEntity<String>(jsonp, headers);
ResponseEntity<String> responseEntity =
rest.exchange(url, HttpMethod.PUT, requestEntity, String.class);
return responseEntity.getBody().toString();
}
Using the method above, i receive a 400 Bad Request
I know my parameters, url and so, are just fine, cause i can do a restTemplate.put request like this:
try {
restTemplate.put(getApiUrl() + "company/" + getCompanyId() + "/appointment/" + appId + "?session_token=" + r.data.session_token, map);
} catch(RestClientException j)
{
return j.toString();
}
The problem (like i said before) is that the try/catch above does not return any response but it gives me a 200 response.
So now i ask, what can be wrong?
Here's how you can check the response to a PUT. You have to use template.exchange(...) to have full control / inspection of the request/response.
String url = "http://localhost:9000/identities/{id}";
Long id = 2l;
String requestBody = "{\"status\":\"testStatus2\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestBody, headers);
ResponseEntity<String> response = template.exchange(url, HttpMethod.PUT, entity, String.class, id);
// check the response, e.g. Location header, Status, and body
response.getHeaders().getLocation();
response.getStatusCode();
String responseBody = response.getBody();
You can use the Header to send something in brief to your clients. Or else you can use the following approach as well.
restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, ...)
You will be able to get a Response Entity returned through that.
Had the same issue. And almost went nuts over it. Checked it in wireshark: The problem seems to be the escape characters from the request body:
String jsonp = "{\"data\":[{\"status\":\"1\"}]}";
The escape character (backslash) is not resolved. The String is sent with the backslashes, which is obviously not a valid json and therefore no valid request(-body).
I bypassed this by feeding everything in with an Object, that is mapping all the properties.

Categories