-
Notifications
You must be signed in to change notification settings - Fork 321
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
Make HTTP::Feature work like rack middleware #767
Comments
This was a deliberate design decision. See the many, many years of previous discussion. Here's a summary: #478 (comment) |
I respect your decision. But is it possible to change the execution orders? Just change client.rb#L84: # res = options.features.inject(res) do |response, (_name, feature)|
res = options.features.to_a.reverse.to_h.inject(res) do |response, (_name, feature)|
feature.wrap_response(response)
end Suppose we have three features, [:logging, :auto_deflate, :auto_inflate] # response in log is compressed
[:logging, :auto_inflate, :auto_deflate] # response in log is compressed
# 1. logging#wrap_request
# 2. auto_deflate#wrap_request
# 3. _REAL_HTTP_REQUEST_
# 4. logging#wrap_response
# 5. auto_inflate#wrap_response
[:auto_deflate, :auto_inflate, :logging] # request in log is compressed
[:auto_inflate, :auto_deflate, :logging] # request in log is compressed
# 1. auto_deflate#wrap_request
# 2. logging#wrap_request
# 3. _REAL_HTTP_REQUEST_
# 4. auto_inflate#wrap_response
# 5. logging#wrap_response
[:auto_deflate, :logging, :auto_inflate] # request/response in log is compressed
# 1. auto_deflate#wrap_request
# 2. logging#wrap_request
# 3. _REAL_HTTP_REQUEST_
# 4. logging#wrap_response
# 5. auto_inflate#wrap_response |
If you're asking if it would be okay for features to be applied to responses to handled in the reverse order from the requests, that makes sense to me, though I would worry somewhat about it breaking existing code if it were done outside of a breaking release. |
Updated, plz see #766 |
Oh. I really like that you've started working on session gem. I was thinking about it for a very long time (and due to some personal issues never had time for that). I was thinkign about a bit different API for that though: session = HTTP::Session.new(...)
session.with do |http|
http.headers(...).get(...)
end The idea I had was to use connection pool, so that connection would be kept alive just like in browsers. |
On the features order of execution — I think we should provide them with the expected order of the execution. In rack middlewares world, you can tell where to inject the middleware. We should come with similar solution, so that features will be executed in predictable order. HTTP.use(:feature_1).use(:feature_2, before: :feature_1) Or using "weights" on features themselves (this will be less predicatble though): class AutoInflateFeature < Feature
weight 9000
...
end
class LoggingFeature < Feature
weight 0
end Weight-based one will allow us to change HTTP.use(:logging, weight: 100) NB: I'm not proposing going russian-doll middleware pattern. But to provide a way to control feature execution order. |
However that ordering is determined, I think reversing that ordering for processing responses as in #766 better maps to the sort of LIFO/FILO ordering you'd get with middlewares, where the ordering for middlewares lives in the call stack |
I totally agree with that. |
IMO, we can turn on the keep-alive feature for all requests when using session, like http = HTTP::Session.new(..., persistent: true).timeout(8).freeze
http.get('https://example.com/abc') # -> make a persistent connection
http.get('https://example.com/def') # -> automatically reuse the connection But in order to work with multiple threads, a bit more work is required. So it not implement yet. |
We may still need a way to adjust execution orders, e.g. http = HTTP.use(:feature_1)
http.get('https://example.com/abc')
http.get('https://example.com/def', features: { feature_2: {} }) # only want to use this feature in this request, and want it to run before :feature_1 But currently it may not necessary. |
I am working on http-session (almost done) to support cookies and caching. I found that the HTTP::Feature does not work like the Rack middleware, e.g. executing orders:
The PR#766 attempts to address this and make HTTP::Feature work more like Rack middleware, so that developers can more easily implement their own features, like auth, retry, cache, etc.
Note that this PR may break some existing code that depends on orders, and replay function in webmock.
The text was updated successfully, but these errors were encountered: