I could give some details about the implementation but basically we used exit(:normal) to force the connection to close. The function above is more or less the plug given to Bandit.
With the last update of Bandit, this returns a 500 error instead. Is there a simple way, callable from this test, to force the connection to close?
Thank you.
Edit: I did Process.exit(conn.owner, :kill) and it seems to work but I am not sure itās very clean
Btw unless you need to hit a real http server like Bandit, you can simulate getting that particular error and asserting how Req handles it by using Req.Test.transport_error/2:
I know this is controversial but we are doing real HTTP in the tests, as there are multiple layers and ways to mock each of them, at some point we decided it was simpler to test the real thing. This is for a custom HTTP client so it must do HTTP properly and this allows to not depend on a particular library such as Req.
That being said I doubt we will move from req anytime soon and our mock_http_server is also an abstraction that could leverage the test features of Req, but this has to be setup properly. Itās on my list though.
I found a lot of people who cleary reject the idea of performing an actual http call during the tests, more so if you also start the test http server from the test (which we do, we never actually call a 3rd party server), especially when alternative solutions are possible like with Req. This is what I mean by controversial, I donāt personally think itās bad.
Itās not controversial at all. Simply good thing done improperly can cause tests to fail. There are cases when you have to make sure that your app correctly handles 3rd-party server response and in such case you simply cache everything and put into git history. This way you have fast and not failing tests and ārealā (but cached) replies.
When the server updates itās API you simply remove cached files and run tests again once and commit changed cache. This way tests do not fail for example if said server is overloaded and therefore responding too late.
This is the 80% Bypass I most commonly need. In fact Iād like to be able to use Req.Test mocks backed by Bandit somehow, if that makes sense, but I couldnāt find the right API. Apologies for hijacking the topic, Iāll bow out now but if it piques anyones interest Iām happy to talk through it further elsewhere.
Itās returning an error because youāre not using the Plug API correctly; the contract is clear that your Plug MUST return a Plug.Conn struct with a set response in order to be valid, and by exiting out of the Plug, youāre not doing that. This is coming to light for you in the 1.6.x release train since weāve been focusing on tightening up error handling at this exact boundary (previously, we were rather loose on this which is why you werenāt seeing any errors, even if you were doing something unsupported). But what youāre seeing is 100% expected behaviour. Thereās an error in your plug implementation, which is obviously server-side, and so is a 5xx series error.
In terms of what youāre attempting to do, thereās nothing explicit in the Plug API that allows you to force the connection closed. Strictly speaking, the Plug API is 1:1 with requests inside a connection (such as keepalive requests within a long-lived HTTP connection, or streams within an HTTP/2 connection). The ācorrectā way to do this (at least in HTTP/1) is found in RFC9112§9.3, and is for the server to send a connection: close header in its response, to which the client should then close the connection on its side.
I know, I know, itās not a valid plug. As I described I am not testing a plug implementation here, but a HTTP client.
Iām looking for a way to make the server crash while in the middle of serving the request, just by using the data from the conn. Killing the owner seems to work fine. So I am obviously expecting that code to return an error.
The behaviour Iām trying to mimic (remote server crashing) is not sending connection: close headers, so iām not sure it would be a good test here, but I may try.
The behaviour Iām trying to mimic (remote server crashing) is not sending connection: close headers, so iām not sure it would be a good test here, but I may try.
Ah! Thatās an oversight on Banditās part (RFC9112§9.6 says we should be sending that header before closing the connection if possible, and itās easily possible to do so).
Just added this behaviour to Bandit, if you want to test against main!
Hello again @mtrudel , I have a question regarding Plug.Conn.send_chunked and Plug.Conn.chunk with Bandit.
Is there any guarantee that when the Plug.Conn.chunk(conn, foo) call returns, the HTTP/TCP layer confirms that the client did receive the data? Or can the connection close after the function returns but before the client has fetched the whole chunk?
This is for SSE streams, I want to know if when I just sent a chunk, I can consider it received by the client.