Skip to content

Commit

Permalink
Rely only on methods defined by the Rack body spec while injecting
Browse files Browse the repository at this point in the history
I cannot be sure that every body can be coerced as an array, the only
thing we can rely on is that all the bodies will respond to each. This
fixes rails#252.
  • Loading branch information
gsamokovarov committed Apr 18, 2018
1 parent 2a05188 commit f9c348f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 37 deletions.
2 changes: 1 addition & 1 deletion lib/web_console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module WebConsole
autoload :Evaluator
autoload :ExceptionMapper
autoload :Session
autoload :Response
autoload :Injector
autoload :Request
autoload :WhinyRequest
autoload :Whitelist
Expand Down
21 changes: 21 additions & 0 deletions lib/web_console/injector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module WebConsole
# Injects content into a Rack body.
class Injector
def initialize(body)
@body = "".dup

body.each { |part| @body << part }
body.close if body.respond_to?(:close)
end

def inject(content)
if position = @body.rindex("</body>")
[ @body.insert(position, content) ]
else
[ @body << content ]
end
end
end
end
16 changes: 7 additions & 9 deletions lib/web_console/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,14 @@ def call(env)
status, headers, body = call_app(env)

if (session = Session.from(Thread.current)) && acceptable_content_type?(headers)
response = Response.new(body, status, headers)
template = Template.new(env, session)
headers["X-Web-Console-Session-Id"] = session.id
headers["X-Web-Console-Mount-Point"] = mount_point

response.headers["X-Web-Console-Session-Id"] = session.id
response.headers["X-Web-Console-Mount-Point"] = mount_point
response.write(template.render("index"))
response.finish
else
[ status, headers, body ]
template = Template.new(env, session)
body = Injector.new(body).inject(template.render("index"))
end

[ status, headers, body ]
end
rescue => e
WebConsole.logger.error("\n#{e.class}: #{e}\n\tfrom #{e.backtrace.join("\n\tfrom ")}")
Expand All @@ -64,7 +62,7 @@ def json_response(opts = {})
headers = { "Content-Type" => "application/json; charset = utf-8" }
body = yield.to_json

Rack::Response.new(body, status, headers).finish
[ status, headers, [ body ] ]
end

def json_response_with_session(id, request, opts = {})
Expand Down
27 changes: 0 additions & 27 deletions lib/web_console/response.rb

This file was deleted.

31 changes: 31 additions & 0 deletions test/web_console/injector_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require "test_helper"

module WebConsole
class InjectorTest < ActiveSupport::TestCase
test "closes body if closable" do
closed = false

body = [ "foo" ]
body.define_singleton_method(:close) { closed = true }

assert_equal [ "foobar" ], Injector.new(body).inject("bar")
assert closed
end

test "support fancy bodies like Rack::BodyProxy" do
closed = false
body = Rack::BodyProxy.new([ "foo" ]) { closed = true }

assert_equal [ "foobar" ], Injector.new(body).inject("bar")
assert closed
end

test "support fancy bodies like ActionDispatch::Response::RackBody" do
body = ActionDispatch::Response.create(200, {}, [ "foo" ]).to_a.last

assert_equal [ "foobar" ], Injector.new(body).inject("bar")
end
end
end

0 comments on commit f9c348f

Please sign in to comment.