vcr/vcr — pull request #276 by myronmarston (2013-03-10 22:21:48+00:00)
Title: Update webmock and excon; use new Excon middleware architecture

@geemus, if you have the time, it would be great to get a code review of my excon middleware here to make sure it's kosher with the semantics of how excon middlewares are supposed to work. In addition, I've got several questions/comments about the middlewares (and excon in general) that arose as I was working on this:

* The scope of a middleware instance is unclear to me. I've written mine here to assume that a middleware instance is tied to exactly one HTTP request. Is this a valid assumption? Would the same HTTP request ever use two different middleware instances (of the same class) for the `request_call` vs `response_call` vs `error_call` callbacks? Or would two HTTP requests ever share the same middleware instance? This is important to nail down and define will in your middleware docs as I need to know how to share state between these different callbacks, and storing it on the middleware instance is the easiest way to achieve that, but that's only safe if a middleware instance is tied to one request.
* The relationship between `response_call` and `error_call` confuses me. VCR's middleware has logic that must run after the request, and in my testing, it appears that sometimes just `response_call` gets invoked after a request, sometimes just `error_call` gets invoked after a request, and sometimes both get called after a request. This is quite confusing, and has led me to "hedge my bets" by having both callbacks, and having both call the same `after_request` logic, which then checks to see if it has already run the `after_request` logic, and, if so, exit early.
* Each of the callbacks receives a params hash. For a single HTTP request, are these different hash instances or the same hash instance? I'm treating them as being different but I suspect they are the same instance and it would simplify my code if I could treat them as the same. If they are the same instance, and if there is the one-to-one request-to-middleware-instance relationship I asked about above, it might be semantically simpler to pass the params/datum hash into the `initialize` method of the middleware, then call each of the callbacks with no args, as that makes it explicit that a particular instance of the middleware is for a particular request, and it has a params hash associated with that that any of the callbacks can operate on.
* I have a bunch of logic I had to copy/paste from Excon to get things to work right, and it would be great if this logic was pulled out into stand-alone, reusable objects in Excon in the interest of centralizing the logic and keeping things DRY. Specifically:
* [This logic](https://github.com/vcr/vcr/blob/update_excon_webmock/lib/vcr/middleware/excon.rb#L181-L206) is kinda complex and is used to construct a full URI from the individual request params. I copied it from Excon long ago.
* [This logic](https://github.com/vcr/vcr/blob/update_excon_webmock/lib/vcr/middleware/excon.rb#L121-L140) streams a stubbed response back through the `response_block`. This is a level of low-level detail that I feel like a middleware shouldn't need to directly concern itself with. If Excon had a `StubbedResponseStreamer` class that was used by the internal mock middleware and was publicly exposed for use by other middlewares like VCR's, it would be wonderful.

Overall, the middleware architecture is really awesome, and is a far more robust, superior approach for VCR to integrate with Excon - so thanks for adding it!