-
Notifications
You must be signed in to change notification settings - Fork 13
Fixes issue #1 #2
base: master
Are you sure you want to change the base?
Conversation
Scratch that, it still doesn't work |
Now fixed! I'd made the incorrect assumption that ActionDispatch::Response inherited from Rack::Response |
Thanks for getting into this. Assigning |
According to https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/response.rb, ActionDispatch::Response seems to duck type to Rack::Response and whatever is acceptable as body. In any case, it gets passed as body into ::call. It can't be passed into the Rack::Response constructor or it would get rewritten - https://github.com/rack/rack/blob/master/lib/rack/response.rb My solution assumes that anything which is not a plain Array must duck type to ActionDispatch::Response, which is technically wrong, although if you pass something that is not a plain ruby Array into the Rack::Response constructor, it's going to come out with class Array. I think Rack and/or Rails might have failed us here. |
That last commit fixes issue #4 |
Hey John, I hope this should do: e225771 Could you please verify that it works? You can put this into your Gemfile to test it:
|
^^ I mean regarding the send_file issue. |
Hi @jistr, thanks for trying to fix all the issues! Unfortunately, the fix you've made doesn't work for me. I don't think you should be creating a new Rack::Response at all, because you're going to lose any information stored as instance variables on an object that is expected to duck type. Also, imagine the performance hit if all rack middleware rewrote every response. You might also break streaming. Instead, I think you should be writing to it. I added a spec here in my original pull request: which checks that Rack::Response objects are preserved. However, this isn't enough, since ActionDispatch::Response does not inherit from Rack::Response. |
Hmm :( I'm not creating a new Rack::Response if the thing returned from app already behaves in a way compatible with Rack::Response, which should be the case of ActionDispatch::Response. This part takes care of it: https://github.com/jistr/mobvious/blob/actiondispatch/lib/mobvious/manager.rb#L27-L31 I'm looking if it responds to #header, #status and #body methods, which ActionDispatch::Response does, and if so, I use it directly instead of creating a Rack::Response. So I wonder what's the practical difference between your solution and mine... The thing with the spec you added is that it passed even on original Mobvious code, so it doesn't really test the issue in question (unless I messed up somewhere). |
And yes, I'm not rewriting response. I return the original thing that the app returns. Also, creating new Rack::Response doesn't rewrite the response, unless I'm mistaken. It's just a wrapper object for more convenient access to the underlying data, but it doesn't create a copy. |
You're right. I can't see how your rack_response? method wouldn't detect ActionDispatch::Response. However Rack::Response.new does by definition create a new object of type Rack::Response. It then writes the strings one by one (ok, no actual copying). My test is wrong because I've been an idiot: https://github.com/johncant/mobvious/blob/master/spec/mobvious/manager_spec.rb#L16 I'll take another look at this stuff later. |
This fixes issue #1! Mobvious::Manager now passes Rack::Response objects correctly.