REST-assured icon indicating copy to clipboard operation
REST-assured copied to clipboard

Unable to have a double receive any non-text body

Open trackness opened this issue 5 years ago • 7 comments

Hello,

I'm unable to send any non-text-based body to an active double, and am unsure as to whether this is by design, or due to error on my behalf.

My Gemfile is as follows:

source 'https://rubygems.org' do
  gem 'rest-assured'
  gem 'rest-client'
  gem 'rubocop'
  gem 'sqlite3' # for rest-assured
end

Steps are as follows:

Given('a {string} cdn') do |destination|
  @full_path = "/#{destination}"
  @ra_destination = RestAssured::Double.create(
      :fullpath => @full_path,
      :verb => 'POST'
  )
  expect(@ra_destination.status).to eq(200)
end

Note the Then is sending a request to simulate the activity of the accompanying java application:

Then('{string} is received at {string}') do |file, uri|
file = File.read("#{CUCUMBER_DIR}/fixtures/#{chunk_name}")
RestClient.post(
    "localhost:4578#{@full_path}#{uri}",
    file,
    :content_type => 'video/mp4',
  )
  requests = @ra_destination.reload.requests
  expect(requests.first.body).to eq(file)
  expect(JSON.parse(requests.first.rack_env)['REQUEST_METHOD']).to eq('POST')
  expect(JSON.parse(requests.first.rack_env)['CONTENT_TYPE']).to eq('video/mp4')
  expect(JSON.parse(requests.first.rack_env)['REQUEST_URI']).to eq("#{@full_path}#{uri}")

This results in the fourth expect failing, with the top several stack trace line being:

2019-11-18 09:34:57 - Encoding::UndefinedConversionError - "\xC0" from ASCII-8BIT to UTF-8:
	/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/sqlite3/quoting.rb:56:in `encode'
	/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/sqlite3/quoting.rb:56:in `_type_cast'

Setting the POST body (and expected requests.body.first to be an arbitrary string causes the test to pass. Note also that this error is also seen when sending a valid curl from the terminal to a live double.

Please advise, thank you.

trackness avatar Nov 18 '19 09:11 trackness

This looks like a missing feature - binary content that is. The error you see looks like an active record error due to the fact that it is trying to store binary data into the text field.

We could change rest-assured to store everything as binary and convert it to text on the way in/out for textual content_types. And NOT convert for video/mp4 (and similar)

artemave avatar Nov 18 '19 09:11 artemave

Thanks for the answer and clarity. Is that an avenue you would consider following in the very immediate future?

trackness avatar Nov 18 '19 09:11 trackness

I can't promise you to get on it soon. But I am generally quick with accepting pull requests :)

artemave avatar Nov 18 '19 10:11 artemave

We could change rest-assured to store everything as binary and convert it to text on the way in/out for textual content_types. And NOT convert for video/mp4 (and similar)

I've had a quick look into this. Storing everything as binary data is quite easy (I came up with a DB migrate file that takes care of this), however REST-assured converts request objects to JSON when responding to the /doubles/:id.json endpoint: https://github.com/artemave/REST-assured/blob/6b716c8c8e2495be4396e25f3943847d542dda15/lib/rest-assured/routes/double.rb#L37

This won't work with binary data. Not sure whether there's a nice trick we could do to workaround the problem.

Another approach would be to return binary data as Base64 strings, however Ruby code that integrates with this Gem needs to explicitly decode it, which is not ideal.

PyvesB avatar Nov 19 '19 15:11 PyvesB

Another approach would be to return binary data as Base64 strings, however Ruby code that integrates with this Gem needs to explicitly decode it, which is not ideal.

I see. Well, it's a bit of an edge case, so maybe that's ok? What code needs to examine the double body anyway? I can only think of web ui that comes with the gem.

artemave avatar Nov 20 '19 07:11 artemave

I see. Well, it's a bit of an edge case, so maybe that's ok? What code needs to examine the double body anyway? I can only think of web ui that comes with the gem.

Actually the bit of code I linked seems to be run each time something like @double.reload is called, so it's not just the Web UI.

PyvesB avatar Nov 20 '19 07:11 PyvesB

Yeah fair enough. Though the purpose of reload is to assert requests, not to check on the double payload - it is likely being set just a few lines above in the test script.

artemave avatar Nov 20 '19 14:11 artemave