::Rack::Deflator throws exception when defined in a mapped API
wolfscaptain opened this issue · comments
Whenever ::Rack::Deflator is defined inside a mapped Goliath::API, it throws an exception about String#each not being defined.
For some reason when Goliath runs the main API with Deflator inside it, it sends the data correctly inside an array, e.g. ["HTML"], but when it is deined in a mapped API, it sends the string directly, so Rack::GzipStream#each fails.
Here's an example code:
class Mapped < Goliath::API
use ::Rack::Deflater # if it's here, Goliath sends "Ok"
def response(env)
[200, {}, "Ok"]
end
end
class MainAPI < Goliath::API
map "whatever", Mapped do
use ::Rack::Deflater # if it's only here and not in Mapped, Goliath sends ["Ok"]
end
end
Your response entity should be something that responds to #each
, e.g. an Array
:
def response(env)
[ 200, {}, [ "Ok" ] ]
end
Recently there has been some discussion on this in rack/rack#376.
It should also include a Content-Type
header, btw. You might want to have a look at the Rack spec.
You didn't understand.
If I put "use ::Rack::Deflater" in the mapped API, Rack::GzipStream#each gets a string, but if I put it in the main API, it gets an array with the string inside it.
In both cases my return from response() is a string.
What I mean is: passing something that responds to #each
as the response body is what the Rack spec requires. Goliath itself is a little more tolerant and happily takes a String instead. But if you mix Goliath stuff with Rack middleware, using an #each
duck type is the least common denominator.
TL;DR Goliath is happy with Strings as response bodies, but Rack::Deflater expects an #each
duck type and thus blows up.
Closing, cutting router from 1.0. Please reopen if this still occurs in generic setup.