I got a request over the weekend to support a client library on the Android platform that cannot submit multipart form data easily. The request was to allow the client to send the raw bytes as the HTTP request body. In order to implement this functionality I of course wanted to spec it out first to make sure I was writing this correctly - it isn't every day that I deal with the raw request body after all.

My spec ended up looking like this...

#./spec/controllers/file_test_api_controller_spec.rb  
⋮
  describe "#raw_upload" do
    before do
      # file_path points to a file I used dd to generate that is 11,776 bytes
      bytes = File.open(file_path, 'rb').read
      @request.env['RAW_POST_DATA'] = bytes
      post :raw_upload, { }, 'CONTENT_TYPE' => 'application/octet-stream'
      @request.env.delete('RAW_POST_DATA')
    end
    subject { response }
    its "status" do
      should == 200
    end
    its "body" do
      should =~ /size.*11776/m
    end
  end
⋮

To access this data directly in your controller, you just use request.raw_post.

Its worth noting that my controller replies with a receipt in JSON that includes the size of the received data which is why the spec regexes the body for it - there's no automagic occurring with my controller's response.

This approach does not work with HTTP PUT as the RAWPOSTDATA request environment variable is cleared when a PUT is performed.

Reference: How to send raw post data in a Rails functional test?