I'm using Spring Cloud Contracts version 2.1.1.
I understand that I can use some value from the original request to validate against some value in the response, and I can use it within another string (i.e. not as is, but concatenated with other strings):
response {
status 200
body(
message: "Hello, ${fromRequest().body('$.name')}!",
)
}
What if I wanted to used some arithmetic on a numeric json value from the request, i.e. validate that response has this value incremented:
response {
status 200
body(
result: ${fromRequest().body('$.count')} + 1
)
}
Or, maybe even two numeric values added, e.g.:
response {
status 200
body(
result: ${fromRequest().query('num1')} + ${fromRequest().query('num2')}
)
}
Obviously the two last snippets are not valid, but illustrate what I'm looking for. Is this somehow possible with current Spring Cloud Contracts?
No it's not valid. The question is why do you want to test that logic. From the point of view of contract testing you should maybe only check that there's a number there?
Related
I'm going to create one rest services in rest dsl xml. On that I have created one routes. For the route I am going to call my own microservices (this is created other project) for using toD uri. Once I get response I am going to take the values from the body (response json). After that again I am going to call other services in the same route based on the response values (we are taking one field in the response).
My question is
how we can take the values from the response in first service
And how to set headers in that respected values in first values..
How to call 2 services in route. Is it possible to call tod uri two times?
Sample code
<toD uri=http://localhost >
<log message =${body} >
(this response is going to set 2nd service query parameter value )
<toD uri=http://localhost? 1 services response values a>
Not sure if I fully understand your case, but here are my answers to your questions:
1) You can select any value from a JSON response with JsonPath. To use it later, you probably want to save it on the Message header
.setHeader("myHeader", jsonpath("$.your.json.path"))
2) Sorry, I don't understand this question :-)
3) Yes, you can make as many .to() or .toD() as you like
However, if you want to call REST services and you use the Camel REST component, you can profit from built-in URI templating. That means perhaps you don't need .toD()
For example
.to("rest:get:hello/{myHeader}")
would insert the value extracted from the JSON response above because the placeholder name is looked up in the message headers and if found replaced with the value of the corresponding message header
.setHeader("myHeader", jsonpath("$.your.json.path")) // assume jsonpath result is "world"
.to("rest:get:hello/{myHeader}") // URI "hello/world" is called
I created a program to get an API response from a URL.
But for some reason it's printing it out in one long line. Is there any way to print it out the way I see it in postman? I guess what I mean is if there is a way to see the response from the API server printed out line by line instead of one long line.
ResponseBody body = response.getBody();
System.out.println("Response Body is: " + body.asString());
The server response is
[RemoteTestNG] detected TestNG version 6.13.1
Status code is 200
Response Body is:
{"request_id":"Z36ec5ee76a4788bfe83655edbbe9f0","status":"OK","data":{ONE LONG STRING OF DATA WITH NO END IN SIGHT!}
You can use prettyPrint method of Response class. Status you will have to print.
(Response to comment)
If your API call return JSON responses, you can use a JSON validator module.
What it does is: you provide a JSON schema, and it compares it with the response. The JSON schema syntax is defined over there: http://json-schema.org/latest/json-schema-validation.html (it looks more complex than it actually is) and here are some examples http://json-schema.org/examples.html. You can define, in your schema, if a field is "required", and also which "type" it should be (string, integer etc.) and many other things!
Here's a simple tutorial that helped me implement it with Rest-Assured: https://blog.jayway.com/2013/12/10/json-schema-validation-with-rest-assured/
How can I make a Spring #Controller return a 400 status code if the client sends any unexpected request parameters?
For example, I have this
public ResponseEntity<String> recommend(
#RequestParam(value = "max-age-seconds", required = false) Long maxAgeSeconds) {
...
}
And the client may have a typo in max-age-seconds, which my application won't recognise and then fallback to the default max age I chose at a later time.
I know I could get the list of all the request parameters with request.getParameterNames() and check one by one, but I'm looking for a neater and more efficient solution.
EDIT: I just found out that 4 years ago it didn't have a built-in solution, I wonder if it's still the case.
How about you call the method request.getParameterMap() and then check that the size of your Map is 1 the key equals "max-age-seconds" and you can even validate the value if you wish. if any of your validations goes wrong then return 400 (or may be 300 with error message "This is Sparta!"). (the last part is a joke...)
I am using Jersey (1.18) to build a REST API for my WebApplication. In a part of my code I have the following snippet.
return Response.status(Status.NO_CONTENT).entity(err_message).build();
where Status is an instance of com.sun.jersey.api.client.ClientResponse.Status;
According to Jersey Documentation NO_CONTENT should return a 204 code, instead of this, the http response has a header with 200 code.
NO_CONTENT
public static final ClientResponse.Status NO_CONTENT
204 No Content, see HTTP/1.1 documentation.
I tried to change the aforementioned code to
return Response.noContent().entity(err_message).build();
But the issue still exists.
As a side note, using NOT_FOUND instead of NO_CONTENT, return a 404 header as expected.
Any suggestion on 'How can I return 204 code?', is this a bug or I am doing something wrong.
Note: Not a duplicate of Returning 200 response code instead of 204
See this SO answer which says,
...204 means "No Content", meaning that the response contains no
entity, but you put one in it. It's likely that Jersey is switching it
to a 200 for you, which is basically identical to a 204 except that it
contains a response entity.
Finally, you can get 204 responses very simply by a couple of built-in
behaviors: void methods and null return values both map to a 204
response. Otherwise, simply return Response.status(204).build().
In other words, if you want "NO_CONTENT" then don't include content in your response.
After a little more digging I have found the problem. The W3c Documentation gives a hint.
I am quoting
10.2.5 204 No Content
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
In my code I have entity(err_message) which causes the problem. By removing it the 204 is returned correctly. I think somehow the Jersey or 'someone' casts the response to 200 since it has content.
Update (02/05/2015)
This blog post link (posted earlier today as an answer and then deleted), gives some additional insights about situation. Based on the content of the blog post, whenever there is any content in the HTTP response the following method is invoked. This method sets the status code back to 200.
private void commitWrite() throws IOException {
if (!isCommitted) {
if (getStatus() == 204)
setStatus(200);
isCommitted = true;
o = responseWriter.writeStatusAndHeaders(size, ContainerResponse.this);
}
}
We can say that Jersey detects that since there is some content in the response, the status code was wrongly set to 204 and it changes it to the appropriate 200.
I have a REST API published with Jersey and documented with Swagger, I also have a Swagger UI installation consuming that API.
Almost all my operations produce application/json and work as expected, except for one GET operation that produces: 'text/plain;charset=utf-8'
When I try to call the service from the Swagger UI, the server logs a javax.ws.rs.NotAcceptableException and returns a 406 response. If I call the same service from a REST client it works as expected.
#GET
#Path("/text")
#Produces(MediaType.TEXT_PLAIN + ";charset=utf-8")
#ApiOperation(value= "Return text")
public Response getText(#QueryParam("user") String user) {
return Response.ok(textService.getTextForUser(user)).build();
}
If I change to #Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") then it works fine, but I don't want to set a wrong content type.
The problem seems to be that Swagger UI is wrongly setting the Accept headers to application/json as can be seen by observing the request:
GET /supertext/text?user=1
...
Accept: application/json
When using the rest client the Accept header are:
GET /supertext/text?user=1
...
Accept: */*
Why is Swagger UI not setting the Accept headers properly?
Can this be configured?
It seems that swagger ui sets the accept header to application/json when it finds that the #Produces annotation contains a single value, otherwise it renders a drop-down list in the ui to choose from the available content types.
In swagger-ui.js:
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
When the drop-down list doesn't exist, the property becomes undefined.
Later in the code, the response content type is set to application/json if the property is null or undefined:
In swagger.js:
if (this.type === "POST" || this.type === "GET" || this.type === "PATCH") {
if (this.opts.responseContentType) {
responseContentType = this.opts.responseContentType;
} else {
responseContentType = "application/json";
}
}
So my solution was to modify the code in swagger-ui.js to make sure that the correct content-type was set, by exploring the produces array and choosing the first element as the response content type:
In swagger-ui.js replace the line:
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
With:
if($("div select[name=responseContentType]", $(this.el)).val() === undefined) {
opts.responseContentType = opts.parent.model.produces[0];
}
else {
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
}
I was also getting the same issue, but the solution was something different.
The problem lied in an unrelated controller, whose mapping was not defined correctly.
On starting the spring-boot application, I was able to see a log something like as follows :
([]) Mapping with class UnrelatedController
Whenever I loaded the swagger UI, a request swagger's API was being made, however response for this API was being displayed, which did not match what swagger was expecting.
Hence the error 406
The solution was to correct the mapping of the UnrelatedController, and everything worked as before. Thanks to Git History!