How can I elminated warnings in Gatling ReponseProcessor - scala

I have some code in my scenario such as
.check(status.is(200), jsonPath("$['resultData'][*]['#contentType']").findAll.saveAs("resultData"))
.check(status.is(500), jsonPath("$['processingError']").find.saveAs("processingError"))
but I keep getting the following
10:36:51.946 [WARN ] i.g.h.a.ResponseProcessor - Request 'GetAllThings' failed: status.find.is(200), but actually found 500
10:36:52.344 [WARN ] i.g.h.a.ResponseProcessor - Request 'GetAllThings' failed: status.find.is(500), but actually found 200
Is there some way I can construct my checks so that I don't get these messages, because I am already handling both cases?
I have tried several variations, but nothing seems to work.

Okay, this does what I want (mostly)
.check(
status.in(Seq(200, 400, 500)),
jsonPath("$['resultData'][*]").findAll.optional.saveAs("resultData"),
jsonPath("$['processingError']").optional.saveAs("processingError")
)
I say mostly because while it solves one problem, it creates another. Basically the 400 and 500 errors are captured, but now they are not marked as KO, so the statistics don't count them. I tried explicitly returning
sesson.markAsFailed
in my exec(), but that does not work, probably because once you are out of the check, the failure does not count (pun intended).

Related

a call to query consoleText returns with HttpStatus 100 - how to deal with that?

I am working on a program than launches Jenkins jobs using the REST API. After the job has completed, I'd like to get its log, so I call http://jenkins.domain.com/job/my_job_name/#/consoleText in my code.
In 75% of the cases that works and I get the text in return. But there a some cases where it comes back with HttpStatus 100 and no text. (Opening the URL with the browser then shows the text, so clearly there is something to return.) (I haven't found any pattern that would explain it, like "exceptionally large log" or so.)
I found no documentation about calls returning 100 and have no idea how to proceed. Simple repeating the call gives the same result. So how can I get the expected result?
Surprisingly "exceptionally large" was the answer. This caused a timeout (followed by some inappropriate handling) in the library that I used to handle the HttpGet. (Fortunately it was fixed very quickly.)

I need simple proxy between 2 rest APIs

My code is working ok for GET/POST/PUT to/from restApi1 and restApi2.
However, my problem I need to implement HEAD/OPTIONS (no body!) and GET uri1
HEAD/OPTIONS could return 204 or 200 depends on a process status. I am getting error "Stream closed". Sounds like Camel want body bytes, but I don't indend to have it. Even I set ExchangePattern.InOnly or optional etc error occur...
What is correct way to see responses and handle requests WITHOUT body, just statuses exchange?
How to see response from restApi2 on Camel rest("/restApi1").head().route().routeId("id1")
.to("direct:restApi2").routeId("/id1").setHeader(Exchange.HTTP_METHOD,constant("HEAD"))
setExchanggePattern(ExchangePattern.OutOptionalIn).recepientList(simple(restApi2));
I figured it out. Need to set '.convertBodyTo(String.class)' even I don't have a body.

403 - Insufficient Permission only on accountSummaries call

I'm getting rejected only on the accountSummaries/list management call, everything else works fine - heck, it works even when executing it from the reference page! I double checked that the account being used was correct and, as I said, I have no issues performing the simple accounts/list call.
I'm using the python library, and for both of those calls no parameters are needed (so the chance of some embarrassing error are very low).
Basically I'm simply getting the service client and performing the simplest possible call:
a = client.AnalyticsManagementClient() # super simple wrapper
a._service.management().accounts().list().execute()
a._service.management().accountSummaries().list().execute()
The first call works fine, the second one returns a 403 error. Anyone have an idea why that might happen?
Full error is HttpError: <HttpError 403 when requesting https://www.googleapis.com/analytics/v3/management/accountSummaries?alt=json returned "Insufficient Permission">
It was just a scope issue: accounts needs at least one among
https://www.googleapis.com/auth/analytics
https://www.googleapis.com/auth/analytics.edit
https://www.googleapis.com/auth/analytics.readonly
while accountSummaries allows only the last two; it seems to be the only one that does not work with the analytics scope, which is the one our client was requesting.

REST design - An operation with multiple possible non-success payloads

I'm trying to design a REST method for an 'Add person' operation that has a bunch of business rules. There are multiple possible non-success payloads (for the business purposes), requiring defined structure (to allow the consumer to parse the detail).
For 'Add a person', one of the following non-successes could happen:
We believe the system already has person.
Payload: The ID of that person
There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Question - Response object
If they're all to return under a single HTTP error status code, would it be right to have a varied object like:
OverrideCode (for (1))
PersonPossibleMatches [] (also for (1))
PersonDuplicateId (for (2))
ErrorList [] (for (3))
And have the consumer + documentation explain the interpretation?
Question - Response code
Is 400 (Bad Request) the correct (or correct enough) HTTP status code for this? We use it largely for the field validation (also scenario (3) - just wondering if business rule / 'intermediate state' things like this are any different.
Are there a more appropriate codes to spread the 3x scenarios over? And is it ok for the payloads to be different?
Thanks.
There are two aspects you need to consider
HTTP response code.
Error response payload.
Point number 1 is relatively simple. You have 400 error code for bad requests. And 409 for conflicting resources. So far simple.
Now let us consider your scenarios:
We believe the system already has person.
Payload: The ID of that person
Design suggestion: you can send a response like below
Response code: 409
{
"error_code": "resource_exists",
"error_description": "Resource person with ID XXX already exists"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/123456",
"rel": "person"
}
]
}
2. There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
Design suggestion:
In this case - you may want to use PUT to override the resource. No need to use special code.
Response Code: 400
{
"error_code": "potential_duplicates",
"error_description": "Potentially the resource is duplicate of one of the following. Please use PUT with the resource ID to update"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/234",
"rel": "person"
},
{
"href": "http://host-name/persons/456",
"rel": "person"
},
{
"href": "http://host-name/persons/789",
"rel": "person"
}
]
}
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Design suggestion: Here you can simply use 400 response code and a meaningful response like the examples above.
This depends in part on how the operation is performed. Since you said the operation has a bunch of business rules, and the system returns a payload with an ID when the person already exists, let's assume the operation is non-idempotent due to unrelated side-effects, performed with a POST to a factory endpoint.
1. We believe the system already has person.
This is a no-brainer. As suggested by others, you should use a 409 Conflict status code, with a body describing the nature of the conflict. In this case, it seems like there's nothing else the user needs to do, and he can move forward to the next step in the workflow. If there's something he can do, it should follow a procedure similar to the next case.
2. There are some possible matches.
Assuming that the clients don't have any key to unambiguously identify a person, which seems to be your case since you're considering possible matches, here you should also use a 409 Conflict status code, with a body describing the nature of the conflict, but with instructions on how to solve it.
Some other answer suggests you to allow an overwrite parameter that could be used any time, other suggests using a PUT, but I disagree with that since there's nothing preventing a client from using the overwrite all the time, or skipping the POST and use the PUT to replace an existent close-match. Also, you may have concurrent clients trying to add or change a person that match each other, or a common existent group, which will lead to an ABA conflict.
The conflict resolution body should return a valid tag for each possible match, and the client should be instructed to resubmit the same request with the If-Match header and the collection of tags. It may be a single tag, as long as it's generated from key data from each member in the collection. This will enforce that the user first must try the request without any override. If there's a conflict the user is forced to specify the exact entities that will be overwritten, and you're protected from inconsistent updates in case someone changes the current state between the first and the second request.
If the tags don't match in the second request, meaning the state was changed by something else between them, you should fail with a 412 Precondition Failed error.
3. General validation errors
This is also a no-brainer. A 400 Bad Request detailing the error, which seems to be standard across your API.
You could use 409 for the duplicate entry - and arguably for the possible duplicate entries with the extra info in the payload.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
A 400 for validation errors would be the expected response.
It is a judgement call at the end of the day and it depends what would be easier for your rest clients and what they are doing.
Here's the design process I use when creating RESTful API responses for error cases:
Design the response payload for the error condition. Regardless of the error code that's used, it is always good practice to return some content within error responses so that clients can learn more about the error and how to avoid it in the future.
If there is an HTTP status code that accurately describes this error already, and it's not already in use for another error case, use that.
If the closest matching error code is already being used for another error case, it's still OK to use that code, but the response payload becomes the place where the different error cases under that code get distinguished from each other. Your documentation should clearly state that inspecting this code wouldn't be enough, and that clients should then also look into the response to see exactly what happened.
If none of the above are applicable, use the closest error code that's appropriate. Just as in #3, the documentation of your response payloads makes this approach possible. If it's an error that the client influenced, make it a 400-range error, probably 400 - Bad Request. If it's the server's fault, then it should be a 500-range error, probably 500 - Internal Server Error.
Please, please, never throw 200 - OK for errors. The world left that nonsense behind in SOAP land, and nobody wants to go back.
Now let's apply that thinking to your error cases:
We believe the system already has that person. As correctly stated in another answer, 409 - Conflict accurately describes that error, so you should just use that. Putting some descriptive error information in the response payload would help new users of your API, even with such a definitive and understandable code.
There are some possible matches. There really isn't an HTTP code that describes this, and it's something that the client could influence, so the closest would be the catch-all code of 400 - Bad Request. Including the list of possible duplicates is an interesting idea, but make sure you don't end up returning enormous responses with huge numbers of possible matches. Also, make sure to also return URIs to those matching resources so that your clients can easily consume them. As for the "override code" suggestion, I wouldn't return that in the payload. Rather, I'd just document a parameter to your "Add a Person" operation that would allow for overrides to occur at any time, not just after a failed first attempt. For example: POST /people?overwrite=true.
General validation errors This is definitely a job for 400 - Bad Request, along with a descriptive error payload. It sounds like you're already allowing an array of errors to be returned from any API call, so that should be good enough to capture all the validation failures for the client-supplied data.
How about explaining it with a payload back; That is how we deal with REST responses for clients.
Response HTTP 409 with following payload response indicating to client what should they do next
`
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request-result>
<http-code>200</http-code>
<description>REST Request is successfully processed</description>
<internal-error-info>Person already Exists</internal-error-info>
<message>Person with <id> already exists in sytem. Try picking different ID/Name combination</message>
<requested-operation>Add a Person</requested-operation>
<resource-name>Person</resource-name>
<status>SUCCESSFUL</status>
</request-result>
`

Invoking halt in sinatra does not set sinatra.error

My use case is that I would like to do error handling in sinatra. For this I am setting up the error handler as follows
error 0..600 do
##logger.error("error reason #{env['sinatra.error']}")
end
The sinatra.error variable gets set fine if the error was caused by explicitly raising an exception
get '/' do
raise "Fail the request"
end
But if halt is used to terminate the request then sinatra.error does not get set. Looking into sinatra code this appears to be as expected because throwing :halt causes the control flow to go all the way up to invoke and thus bypassing the setting of sinatra.error variable.
My question is how to use the error handler along with the halt so that I can get the cause of the error in the error handler.
I think the behavior you're seeing stems from the intended purpose of halt. When you call it, you aren't necessarily signaling in error; you just want execution to stop immediately, which can be particularly useful in a filter. If you check Sinatra's README, it says that you use halt to "immediately stop a request within a filter or route use". Granted, you will usually do it because of an error.
It is also interesting to notice that the error handler you defined gets called not only when errors occur, but also when regular requests are served, including ones with status 200. And in those cases, env[sinatra.error] won't be set either.
What you can do in your error handler is to check for an exception and, if it's not available, check the response code. For example (note that this is a classical application):
error 0..600 do
boom = #env['sinatra.error']
status = response.status
case
when boom != nil
puts 'exception: ' + boom
when status != 200
puts 'error: ' + status
end
end
One consequence is that, in this handler, normal requests are indistinguishable from those interrupted by halt, because both generate a 200 status code. However, if you are using halt to report errors, then you should be using an error code like 500 anyway.