-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditions under which Maxwell.Error are raised #33
Comments
The original purpose is for |
I think code like that is quite error prone unfortunately, for example, status 206 means it's only partial content, and not all 200 status codes return a response body (e.g. 204). Some status codes in the 300 range are not a problem (like 304), but others are (like 300, or 303). Anything in the 400-500 ranges will potentially have a body, but not what the user expects, which will break their pipeline as well. My point being, blindly asking for the response body and then piping into something else without checking status codes explicitly is a bad idea. Building up the connection and then executing it at the end is a perfect use case for pipelining, but I think one should bind the result and check it after that in order to do the correct thing. I know I was already bitten by this behaviour since all other HTTP clients I've used only raise errors when actual exceptional conditions occur, such as the adapter failing to establish a connection. I consider getting a response of any kind successful, and I think most other users will expect that as well. This is also how Tesla works, and if we're interested in getting the two projects aligned, I think this might be a good change to make in that direction. I'll respect your decision either way here, but I would strongly recommend reconsidering the current behaviour, as I think it's an error-prone API to expose to users. |
how about: def unquote(method_exception)(conn, expect_status \\ nil ) do
case unquote(method)(conn) do
{:ok, %Maxwell.Conn{status: status} = new_conn} ->
case expect_status do:
nil -> ok;
_ is_integer(expect_status) ->
unless status == expect_statuses do
raise Maxwell.Error, {__MODULE__, :response_status_not_match, new_conn}
end
_ is_list(expect_status) ->
unless status in expect_statuses do
raise Maxwell.Error, {__MODULE__, :response_status_not_match, new_conn}
end
end;
{:error, reason, new_conn} -> raise Maxwell.Error, {__MODULE__, reason, new_conn}
end
new_conn
end I want to keep |
@bitwalker @zhongwencool In general, when to raise an error should be determined by the expectation of the invoker. Even we consider a remote endpoint's failure to be expected ( return normal result as usual), we should at least raise an error for 4xx, cuz, 4xx indicates a client error and invoker could not fix an error caused by itself ( you should not expect you code to live through an As for the argument for 206, 204, I think all the 2xx indicate a success, as the Status Code Definitions defined, so the clients are expected to handle all the possible status codes, cuz it should be part of the protocol. If users need to handle the content from a 4xx or 5xx response, they should turn to the functions without bang(!), cuz this function take all kinds of status as expected. |
I think you make good points @secretworry. I've converted over to using the non-bang versions anyway due to this behavior, though I think it still potentially could throw people off coming from other HTTP clients, but as long as it's clearly documented with attention drawn to the difference, it's not a big deal. I'll change this to a documentation issue. |
Sorry to jump in late, but I want to make the opposite case about error expectations in http clients. The comparison with file reading is interesting, but I don't think it applies here. Http services vary immensely with how they are implemented and how they are meant to be consumed. In some cases, 404s are expected responses, not unexpected. Even 500s, in my opinion, are still not worthy of raising an error, because the request/response cycle completed successfully, and the response may even have a body. I've always lived by one rule when it comes to general purpose http clients: You only raise on connection errors. i.e. the connection couldn't be established, the host does not exist, connection dropped half way through, server responded with non-http response, etc. If you got a valid http response from a server after making a request, you shouldn't raise an error. It's the client implementors job to interpret http response codes the way they need for their particular situation. Anyway, just my 2 cents! |
@zhongwencool I think there is another important change we should make. Currently, if you call
get!/1
, it raises if the status code is not in the range200..299
or if an error is returned. I think raising in this situation isn't a good idea. If the request succeeded, but the status code wasn't successful, say 404, we should still returnMaxwell.Conn.t
instead of raising, and let the user check the status code to determine what to do with the request, and only raiseMaxwell.Error
if an actual adapter/middleware error occurs.Thoughts?
The text was updated successfully, but these errors were encountered: