rubysinatrarack

How to pass raw binary data to the put() method of rack/test?


I'm doing this:

require 'rack/test'
data = # some binary data, for example, ZIP archive
put('/foo', data, 'content_type' => 'application/octet-stream')

Works just fine, until I put the % symbol into the data. In this case, I get this:

Invalid query parameters: invalid %-encoding ... (long exception text)

I don't want to Base64-encode or to CGI-encode my data, because the server-side code works just fine without the test. The problem is the way I'm using Rack. Somehow I have to inform it not to touch my data and send it "as is" to Sinatra. How?

This code reproduces the problem (just run it as is, you will see what's printed):

require 'sinatra'
require 'minitest/autorun'
require 'rack/test'

put '/foo' do
  'OK'
end

class FooTest < Minitest::Test
  include Rack::Test::Methods

  def app
    Sinatra::Application
  end

  def test_me
    put('/foo', 'hello % world')
    assert_equal(200, last_response.status, last_response.body)
  end
end

I'm getting this:

  1) Failure:
FooTest#test_me [a.rb:18]:
Invalid query parameters: invalid %-encoding (hello % world).
Expected: 200
  Actual: 400

However, if I remove the % symbol, the test passes.


Solution

  • You can get the test passing by specifying the Content-Type header:

    def test_me
      put('/foo', 'hello % world', 'CONTENT_TYPE' => 'application/octet-stream')
      assert_equal(200, last_response.status, last_response.body)
    end
    

    Note that the key has to be uppercase as shown in the examples for Rack::Test.