Restassured request with spec doesn't get response status logged - java

I want my Restassured request with spec get response status logged.
My request is
given()
.spec(requestSpec)
.when()
.get("/" + userId)
.then()
.spec(responseSpec)
.extract().as(User.class)
;
My spec is
public static ResponseSpecification responseSpec = new ResponseSpecBuilder()
.expectStatusCode(200)
.log(STATUS)
.log(BODY)
.expectBody(notNullValue())
.build();
}
But there is no response status in the log unless I add .log().status() to my request.
Pls tell me how can I fix this.
UPDATE
Following Ashish Patil advice I updated my request but without result
LogConfig logconfig = new LogConfig().enablePrettyPrinting(true);
RestAssured.config().logConfig(logconfig);
given()
.spec(requestSpec)
.when()
.get("/" + userId)
.then()
.spec(responseSpec)
.extract().as(User.class)
;

Question didn't specify if you have set LogConfig before declaring your responseSpec. So you might need to declare LogConfig first to use log method as mentioned in doc :
LogConfig logconfig = new LogConfig().enablePrettyPrinting(true);
RestAssured.config().logConfig(logconfig);
And afterwords you can declare your responseSpec as per your question.

Actually, it's a bug. ResponseSpecification only supports one LogDetail at a time. For example:
...
.log(STATUS)
.log(BODY)
...
--> it will log BODY, not STATUS, because it is a variable declared
private LogDetail responseLogDetail, the latter value will override the previous value.
ResponseSpecificationImpl logDetail(LogDetail logDetail) {
this.responseLogDetail = logDetail
this
}

Related

Access response status code for successful requests using Spring WebClient

I need to be able to access the status code of a request. The call can be successful in either of two ways 200 or 201. This is obvious when calling via postman but using the web client, so far I haven't been able to determine which has occurred.
webClient.post()
.uri(url)
.header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.AUTHORIZATION, bearerToken)
.bodyValue(bodyMap)
.retrieve()
.onStatus(
HttpStatus.BAD_REQUEST::equals,
response -> response.bodyToMono(String.class).map(Exception::new))
.bodyToMono(Map.class)
I was thinking maybe I could set an integer variable using within the onStatus() lambda function. Is it even possible to access external variables within a lambda function?
int responseStatus;
// post call
.onStatus(
HttpStatus.CREATED::equals,
response -> ... // do something to set responseStatus
You could use .toEntity(Class<T> bodyClass) method to get entity wrapped in response object ResponseEntity<T>
var response = webClient.post()
.uri(uri)
.retrieve()
.toEntity(Map.class)
.map(res -> {
if (res.getStatusCode().equals(HttpStatus.OK)) {
...
}
return res.getBody();
});

Sending request body in GET method not working

Im currently in a task in which i have to send a GET request with a body. Im a aware this isn't a good practice and that i should send the json through query params.
But I'm bound to do it like this.
So let's continue. I use RestTemplate with exchange but due to SimpleClientHttpRequestFactory implementation i cannot send a body with a GET method.
RestTemplate template = new RestTemplate(new CustomClientHttpRequestFactory());
httpHeaders.setContentType(APPLICATION_JSON);
httpHeaders.set("token", token.getToken());
httpHeaders.set("companyId", companyId);
URI uri = new URI(getInspectionsUrl);
HttpEntity<InspectionsInputDTO> entity = new HttpEntity<InspectionsInputDTO>(inputDTO, httpHeaders);
response = template.exchange(uri, GET, entity, InspectionsResponseDTO.class);
After some research i found the following code:
class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
#Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
super.prepareConnection(connection, httpMethod);
if ("GET".equals(httpMethod)) {
connection.setDoOutput(true);
}
}
}
// RestTemplate initialization
RestTemplate template = new RestTemplate(new CustomClientHttpRequestFactory());
This tries to override SimpleClientHttpRequestFactory httpMethod allowance but id does not work. The question is, how can i send a Request BODY in GET request with RestTemplate. Maybe there is another way to override SimpleClientHttpRequestFactory. Im new in this strange world of spring, sorry if im saying something wrong (:

Add AWS Signature Header to all rest assured requests

I'm trying to call an get api which is hosted in aws api gateway via rest-assured
I'm able to sign the request and make a call. But to sign the request, I need to pass the full url to AWS to generate the Authorization Header.
For Ex. If I'm going to access an an endpoint
https://my-aws-api.com/basepath/v1/request/123
I need to sign the request via AWSSigner which needs the full endpoint to do so.
My current approach
String baseURI="https://my-aws-api.com";
String basePath="basepath/v1";
String requestPath="request/123";
String endpoint=baseURI+"/"+basePath+"/"+requestPath;
Map<String,String> signedHeaders= aws4sign(endpoint,defaultHeaders);
given()
.log().ifValidationFails()
.headers(signedHeaders)
.when()
.get(endpoint)
.then()
.log().ifValidationFails()
.statusCode(200);
If I do that , then I cant use RestAssured's baseURI, basePath and path params
I want to access it like
RestAssured.baseURI="https://my-aws-api.com";
RestAssured.basePath="basepath/v1";
given()
.log().ifValidationFails()
.pathParam("reqID", "123")
.when()
.get("request/{reqID}")
.then()
.log().ifValidationFails()
.statusCode(200);
AwsSigner
public static Map<String, String> aws4Sign(String endpoint, Map<String, String> headers) throws URISyntaxException {
String serviceName = "execute-api";
AWS4Signer aws4Signer = new AWS4Signer();
aws4Signer.setRegionName(EU_WEST_1.getName());
aws4Signer.setServiceName(serviceName);
DefaultRequest defaultRequest = new DefaultRequest(serviceName);
URI uri = new URI(endpoint);
defaultRequest.setEndpoint(new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "", "", ""));
defaultRequest.setHttpMethod(HttpMethodName.GET);
defaultRequest.setResourcePath(uri.getRawPath());
defaultRequest.setHeaders(headers);
aws4Signer.sign(defaultRequest, DefaultAWSCredentialsProviderChain.getInstance().getCredentials());
return defaultRequest.getHeaders();
}
So My question is there any way, I can intercept the RestAssured's request before it makes the call, so that I can get the fully generated end point and add the aws signed header to the call.
I am not familiar with this library but from briefly reading its documentation and Javadoc, you should be able to use a RequestFilter to inspect and alter a request before it is sent out.
Take a look at the Filter section of the user guide.
Thanks to #Ashaman.
The Filter Section is what I'm looking for
You can get the uri and other headers that were passed with requests from RequestSpec and then send it to the function to sign them and remove the old headers and put the new headers. Then forward the request
#BeforeAll
public void init() {
RestAssured.baseURI = "https://my-aws-api.com";
RestAssured.filters((requestSpec, responseSpec, ctx) -> {
Map<String, String> headers = requestSpec.getHeaders()
.asList()
.stream()
.collect(Collectors.toMap(Header::getName, Header::getValue));
Map<String, String> signedHeaders = aws4sign(requestSpec.getURI(), headers);
requestSpec.removeHeaders();
requestSpec.headers(signedHeaders);
return ctx.next(requestSpec, responseSpec);
});
}
And for the tests I can use the features of Rest Assured normally
given()
.log().ifValidationFails()
.pathParam("reqID", "123")
.when()
.get("request/{reqID}")
.then()
.log().ifValidationFails()
.statusCode(200);

How to send a Content-Type form-data request using rest assured?

I need to invoke a form-data typed API using Rest Assured. Here is my code.
private Map<String, String> getFormParamsMap() {
Map<String, String> formParams = new HashMap<>();
formParams.put("creatorId", "Instructor1");
formParams.put("creatorPlatform", "Web");
formParams.put("creatoredSource", "File");
formParams.put("creatoredType", "Auto");
formParams.put("deckId", "5a605b472e02d86561172dad");
formParams.put("userId", "kind");
return formParams;
}
public void invoke() {
response = given()
.header("Content-Type", "application/form-data")
.header(AUTHORIZATION_HEADER_NAME, accessToken) //Some API contains access token to run with the API
.headers(headers)
.formParams(getFormParamsMap()) // requestParamsMap here.
.when()
.post(invokingEndpoint);
}
When I execute this, I am getting the below error.
Message: java.lang.IllegalArgumentException: Don't know how to encode creatorPlatform=Web&creatoredType=Auto&deckId=5a605b472e02d86561172dad&creatorId=Instructor1&creatoredSource=File&userId=kind as a byte stream.
Please use EncoderConfig (EncoderConfig#encodeContentTypeAs) to specify how to serialize data for this content-type.
For example: "given().config(RestAssured.config().encoderConfig(encoderConfig().encodeContentTypeAs("application/form-data", ContentType.TEXT))). .."
Stack Trace:
io.restassured.internal.http.EncoderRegistry.encodeStream(EncoderRegistry.java:130)
When I use .config(RestAssured.config().encoderConfig(encoderConfig().encodeContentTypeAs("application/form-data", ContentType.TEXT))) in the invoke() method, it gives the result as below.
{
"status": 400,
"message": "Content type 'application/x-www-form-urlencoded;charset=ISO-8859-1' not supported",
"error": "Bad Request",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException"
}
My request is not x-www-form-urlencoded type, it is form-data type. I can execute it using postman.
Appreciate your support on this.
Thanks.
I have solve this issue by using encodeContentTypeAs("multipart/form-data", ContentType.TEXT)
Ex:-
public void invoke() {
response = given()
.config(
RestAssured.config()
.encoderConfig(
encoderConfig()
.encodeContentTypeAs("multipart/form-data", ContentType.TEXT)))
.headers(headers)
.formParams(formParams)
.when()
.post(oAuthBaseURI).then().extract().response();
}
Please add the consumer as well.
See here for the encoders available for Rest Assured.
This might be causing the problem -
encodeContentTypeAs("application/form-data", ContentType.TEXT)
You can also try this -
.encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false).encodeContentTypeAs("application/form-data", ContentType.TEXT));
As far as I can tell, headers(headers) method replaces all headers, and then RestAssured uses x-www-form-urlencoded content type as default.
Try adding "Content-Type" header after the call to headers(headers).

How to add query parameters to a HTTP GET request by OkHttp?

I am using the latest okhttp version: okhttp-2.3.0.jar
How to add query parameters to GET request in okhttp in java ?
I found a related question about android, but no answer here!
For okhttp3:
private static final OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
public static void get(String url, Map<String,String>params, Callback responseCallback) {
HttpUrl.Builder httpBuilder = HttpUrl.parse(url).newBuilder();
if (params != null) {
for(Map.Entry<String, String> param : params.entrySet()) {
httpBuilder.addQueryParameter(param.getKey(),param.getValue());
}
}
Request request = new Request.Builder().url(httpBuilder.build()).build();
client.newCall(request).enqueue(responseCallback);
}
Here's my interceptor
private static class AuthInterceptor implements Interceptor {
private String mApiKey;
public AuthInterceptor(String apiKey) {
mApiKey = apiKey;
}
#Override
public Response intercept(Chain chain) throws IOException {
HttpUrl url = chain.request().url()
.newBuilder()
.addQueryParameter("api_key", mApiKey)
.build();
Request request = chain.request().newBuilder().url(url).build();
return chain.proceed(request);
}
}
I finally did my code, hope the following code can help you guys. I build the URL first using
HttpUrl httpUrl = new HttpUrl.Builder()
Then pass the URL to Request requesthttp hope it helps .
public class NetActions {
OkHttpClient client = new OkHttpClient();
public String getStudentById(String code) throws IOException, NullPointerException {
HttpUrl httpUrl = new HttpUrl.Builder()
.scheme("https")
.host("subdomain.apiweb.com")
.addPathSegment("api")
.addPathSegment("v1")
.addPathSegment("students")
.addPathSegment(code) // <- 8873 code passthru parameter on method
.addQueryParameter("auth_token", "71x23768234hgjwqguygqew")
// Each addPathSegment separated add a / symbol to the final url
// finally my Full URL is:
// https://subdomain.apiweb.com/api/v1/students/8873?auth_token=71x23768234hgjwqguygqew
.build();
System.out.println(httpUrl.toString());
Request requesthttp = new Request.Builder()
.addHeader("accept", "application/json")
.url(httpUrl) // <- Finally put httpUrl in here
.build();
Response response = client.newCall(requesthttp).execute();
return response.body().string();
}
}
As mentioned in the other answer, okhttp v2.4 offers new functionality that does make this possible.
See http://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/HttpUrl.Builder.html#addQueryParameter-java.lang.String-java.lang.String-
This is not possible with the current version of okhttp, there is no method provided that will handle this for you.
The next best thing is building an url string or an URL object (found in java.net.URL) with the query included yourself, and pass that to the request builder of okhttp.
As you can see, the Request.Builder can take either a String or an URL.
Examples on how to build an url can be found at What is the idiomatic way to compose a URL or URI in Java?
As of right now (okhttp 2.4), HttpUrl.Builder now has methods addQueryParameter and addEncodedQueryParameter.
You can create a newBuilder from existing HttoUrl and add query parameters there. Sample interceptor code:
Request req = it.request()
return chain.proceed(
req.newBuilder()
.url(
req.url().newBuilder()
.addQueryParameter("v", "5.60")
.build());
.build());
Use HttpUrl class's functions:
//adds the pre-encoded query parameter to this URL's query string
addEncodedQueryParameter(String encodedName, String encodedValue)
//encodes the query parameter using UTF-8 and adds it to this URL's query string
addQueryParameter(String name, String value)
more detailed: https://stackoverflow.com/a/32146909/5247331

Categories

Resources