Can I check for an omitted HTTP request with Citrus framework? - integration-testing

I have built a testsuite for a service orchestration with Citrus framework.
In one case, when the former request results in an "empty" response, the last orchestration step, a HTTP request, is skipped.
How can I test that this last request is NOT executed? I did not found a way to do this.
When I do not check this with an explicit expectation, the test is successful no matter if a request is executed or not.
I have an HTTP server simulation in place to respond according to the request. What I was looking for is something like
runner.http(action -> action.server(simulation)
.receiveNothingDuring(5000)
);
to wait for 5 seconds for a request to arrive and SUCCEED if nothing arrives. This is kind of the inverse of the normal receive assertion.

You can use the receiveTimeout action that is exactly what you need:
runner.receiveTimeout(action -> action.endpoint(simulation)
.timeout(5000));
See also descriptions in docs

Related

How to implement a "delivery receipt" for http requests

Is there a way to implement a "delivery receipt", or, "quick response", from the server before the start of a long running process (that will delay the actual response content)?
I mean this:
request -> server receives -> res.send(200) ((but keep this 'res' alive!)) -> server long running process -> res.send("actual response")
This would be very useful in the app side, so I get to know that timeouts are really happening because of the process and not because the server is offline. Also, I wanted to avoid making two requests, one following the other one.
HTTP Status Code 100 CONTINUE can be used for this purpose. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.1
According to the RFC, 100 Continue is an interim response which must be followed by a final response once the request has been completed.

Why is it useful to convert HEAD requests to GET requests?

In a new Phoenix app the Plug.Head plug is present by default and I was intrigued about its significance.
I know that "the HEAD method is identical to GET except that the server MUST NOT send a message body in the response".
I think the official Phoenix guides are top-notch but this threw me off in the Routing guide:
Plug.Head - converts HEAD requests to GET requests and strips the
response body
If HEAD requests are without a body then why is this needed? I thought maybe to rein in malformed requests but looking at the Plug.Head implementation, it just switches the HEAD method to GET.
def call(%Conn{method: "HEAD"} = conn, []), do: %{conn | method: "GET"}
def call(conn, []), do: conn
end
The closest thing I was able to find on this topic is a question on ServerFault but it was related to NGINX and a flawed application logic where HEAD requests needed to be converted to GET and the respective GET responses back to HEAD.
Since Phoenix is largely inspired by Rails, you can safely bet Plug.Head is inspired by Rack::Head.
A HEAD request returns the same response as GET but with headers only. So to produce the correct headers, they're routed to GET actions in your Phoenix app.
However to produce the correct (empty) body, the response's body must be stripped. Because Rack::Head is middleware, it gets to do so after it gets the response from controllers.
In contrast, Plug's architecture works more like a pipeline, Plug.Head modifies the method and passes conn along, but never sees it again.
If you see cdegroot's answer, the responsibility to strip the response's body is passed to the Plug.Conn.Adapter to implement (i.e. the webserver).
AFAICT, the idea is that Plug.Head just ensures that the request is processed as a GET; the second part of implementing HEAD, which is not sending a body, is done by the Plug connection adapters. The documentation for most callbacks, like send_resp, specifies that "If the request has method "HEAD", the adapter should not send the response to the client."

Status code 400 or 200 for error on another micro-service

My application is currently composed of two micro-services :
A. Subscription micro-service
B. Payment micro-service
It also uses another external service:
C. Payment provider
If a user tries to create a subscription with an invalid card number (let's say his card is blocked) the C. service will return me a 200 with a "success" parameter to "false" (I don't handle this service so I can't do anything about that).
Now my question is, what status code should the Payment (B) and Subscription (A) micro-services return ?
I'm not sure if it's a 4** or a 200 (with a success parameter) because the request itself is ok, the input format is ok (even if the data inside it is invalid).
In this situation, a 200 clearly isn't correct, because the request wasn't successful.
My recommendation in such cases is HTTP 422 Unprocessable Entity, which is defined in WebDAV but widely understood, and indicates that the request was syntactically valid but had semantic errors that prevented successful processing.
If the request is syntactically correct - e.g. card number matches some given regex, but is invalid in an another way it definitely should not be 400 Bad Request. This is simply not a bad request.
It also should no return any of 2XX codes since this codes are dedicated for successful responses and - as you set in body success = false is not a request that was processed successfully.
The code that will be the most appropriate will be 409 Conflict along with clear message describing the problem. It indicates that request failed, clarifies why and states explicitly that after correcting the request it can be resubmitted.

Does 200 mean the request successfully started or successfully finished?

I realize this might sound like an odd question, but I'm seeing some odd results in my network calls so I'm trying to figure out if perhaps I'm misunderstanding something.
I see situations where in isolated incidents, when I'm uploading data, even though the response is 200, the data doesn't appear on the server. My guess is that the 200 response arrives during the initial HTTP handshake and then something goes wrong after the fact. Is that a correct interpretation of the order of events? Or is the 200 delivered once the server has collected whatever data the sending Header tells it is in the request? (cause if so then I'm back to the drawing board as to how I'm seeing what I'm seeing).
It means it has been successfully finished. From the HTTP /1.1 Spec
10.2.1 200 OK
The request has succeeded. The information returned with the response is dependent on the method used in the request, for example:
GET an entity corresponding to the requested resource is sent in the response;
HEAD the entity-header fields corresponding to the requested resource are sent in the response without any message-body;
POST an entity describing or containing the result of the action;
TRACE an entity containing the request message as received by the end server.
Finished. It doesn't make sense otherwise. Something might go wrong and the code could throw an error. How could the server send that error code when it already sent 200 OK.
What you experience might be lag, caching, detached thread running after the server sent the 200 etc.
A success reply, like 200, is not sent until after server has received and processed the full request. Error replies, on the other hand, may be sent before the request is fully received. If that happens, stop sending your request.

Node.js http request pipelining

So, I want to use node.js and http request pipelining, but I want to use HTTP only as a transport, nothing else. I am interested in exploiting the request pipelining feature. However, one problem that I am running into is that till a send a response to a previous request, the next requests's callback isn't fired by node. I want a way to be able to do this. I shall be handling the ordering of results in the application. Is there a way to do this?
The HTTP RFC mentions that the responses should be in order, but I don't see any reason for node.js to not call the next callback till the 1st one is responded to. The application can in theory send the response to the 2nd query as a response to the 1st one (as long as there is some way for the recipient to know that it is a response to the 2nd one).
The HTTP client in NodeJS does not support pipelining. (Slightly old post from Ryan, but I'm fairly sure it still holds.)

Resources