Skip to content

Commit b0e5889

Browse files
davidstosikbf4
andauthored
Allow response_body_formatter config to format "binary" responses (#458)
* Allow response_body_formatter config to format "binary" responses Following this issue on Rack's repository: [Fix incorrect MockResponse#body String encoding](rack/rack#1486), it looks like we can expect, from now on, that Rack's `response_body` encoding will be `Encoding::ASCII_8BIT`: > I think the response body should probably always be ASCII-8BIT. Rack can't really know anything about the encoding of the bytes that users want to send. At the end of the day, it's just bytes written to the socket, and I don't think Rack should have any opinion about the encoding the user sends. Therefore, `rspec_api_documentation` cannot rely on `response_body.encoding` to determine whether the response is binary data or not. This line becomes incorrect: https://github.com/zipmark/rspec_api_documentation/blob/81e5c563ce6787f143cf775c64e2bd08c35d3585/lib/rspec_api_documentation/client_base.rb#L90-L91 The real fix would be to figure out a better way to define whether a string is binary or not, but I believe this is a bit outside the scope of my knowledge. In this PR, I'm focusing on giving any application using the `rspec_api_documentation` the choice on how to process the response_body, and particularly on how to detect binary data, while not altering `rspec_api_documentation`'s default behaviour. As an additional benefit, this change would allow an application to display friendlier responses in the documentation for some binary types. For example, PNG data: ```rb Proc.new do |content_type, response_body| # http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature if response_body[0,8] == "\x89PNG\r\n\u001A\n" "<img src=\"data:image/png;base64,#{Base64.strict_encode64(response_body)}\" />" elsif content_type =~ /application\/.*json/ JSON.pretty_generate(JSON.parse(response_body)) else response_body end end ``` * Update README.md Co-Authored-By: Benjamin Fleischer <bf4@users.noreply.github.com>
1 parent adb498a commit b0e5889

File tree

3 files changed

+8
-8
lines changed

3 files changed

+8
-8
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ RspecApiDocumentation.configure do |config|
252252

253253
# Change how the response body is formatted by default
254254
# Is proc that will be called with the response_content_type & response_body
255-
# by default response_content_type of `application/json` are pretty formated.
255+
# by default, a response body that is likely to be binary is replaced with the string
256+
# "[binary data]" regardless of the media type. Otherwise, a response_content_type of `application/json` is pretty formatted.
256257
config.response_body_formatter = Proc.new { |response_content_type, response_body| response_body }
257258

258259
# Change the embedded style for HTML output. This file will not be processed by

lib/rspec_api_documentation/client_base.rb

+3-6
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,9 @@ def headers(method, path, params, request_headers)
8787

8888
def record_response_body(response_content_type, response_body)
8989
return nil if response_body.empty?
90-
if response_body.encoding == Encoding::ASCII_8BIT
91-
"[binary data]"
92-
else
93-
formatter = RspecApiDocumentation.configuration.response_body_formatter
94-
return formatter.call(response_content_type, response_body)
95-
end
90+
91+
formatter = RspecApiDocumentation.configuration.response_body_formatter
92+
formatter.call(response_content_type, response_body)
9693
end
9794

9895
def clean_out_uploaded_data(params, request_body)

lib/rspec_api_documentation/configuration.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ def self.add_setting(name, opts = {})
118118
# See RspecApiDocumentation::DSL::Endpoint#do_request
119119
add_setting :response_body_formatter, default: Proc.new { |_, _|
120120
Proc.new do |content_type, response_body|
121-
if content_type =~ /application\/.*json/
121+
if response_body.encoding == Encoding::ASCII_8BIT
122+
"[binary data]"
123+
elsif content_type =~ /application\/.*json/
122124
JSON.pretty_generate(JSON.parse(response_body))
123125
else
124126
response_body

0 commit comments

Comments
 (0)