3

I spent about two days without success trying to send custom headers with Rack::Test. I just can't send any header into my app. I found a lot of examples in the net with the similar code -- method( address, body, headers ), but for me they don't work at all.

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]

# grep rack  Gemfile.lock
    rack (2.0.4)
    rack-protection (2.0.1)
      rack
    rack-test (1.0.0)
      rack (>= 1.0, < 3)
      rack-protection (>= 1.5.0)
      rack (~> 2.0)
      rack-protection (= 2.0.1)
  rack-test

The code in app (sinatra):

$log = Logger.new STDERR
class MyApi < Sinatra::Application
  before do
    $log.debug{ "Headers: #{ headers.keys.inspect }" }
  end
  get '/offers' do
    #... some code
  end
  post '/offers' do
    # .. some another code
  end
end

spec/api_spec.rb

RSpec.describe MyApi, '/offers' do
  include Rack::Test::Methods
  def app
    MyApi
  end

  context 'авторизация' do
    it 'правильная - get с токеном' do
      get '/offers', nil, {
        'X-Auth' => 'some key'
      }
      $log.debug{ "ENV was: '#{ last_request.env.keys }'" }
    end
    it 'правильная - post с токеном' do
      post '/offers', '', {
        'Content-Type' => 'application/json; charset: utf-8',
        'X-Auth' => 'some long key'
      }
    end
  end
end

Output contains for both tests:

Headers: ["Content-Type"]
...
ENV was: '["rack.version", "rack.input", "rack.errors",
"rack.multithread", "rack.multiprocess", "rack.run_once", 
"REQUEST_METHOD", "SERVER_NAME", "SERVER_PORT", "QUERY_STRING", 
"PATH_INFO", "rack.url_scheme", "HTTPS", "SCRIPT_NAME", "CONTENT_LENGTH", 
"rack.test", "REMOTE_ADDR", "X-Auth", "HTTP_HOST", "HTTP_COOKIE", 
"sinatra.commonlogger", "rack.logger", "rack.request.query_string", 
"rack.request.query_hash"]'
Dimitri
  • 623
  • 7
  • 14

2 Answers2

7

This code is working:

get '/offers', nil, { 'X-Auth' => 'long key' }

And this also is correct:

header 'X-Auth', 'some key'
get '/offers'

I changed the manner I look for that header in app:

request.get_header('HTTP_X_AUTH') || request.env['X-Auth']

The first - get_header was triggered when I call my app with curl, the last - request.env - when in tests.

Dimitri
  • 623
  • 7
  • 14
  • Also found that: https://stackoverflow.com/questions/25660827/accessing-headers-from-sinatra/35689150 – Dimitri Apr 24 '18 at 11:46
  • 1
    Your "also correct" version is the first answer posted anywhere I've found (in hours) which Actually Sets the Headers. Thanks So Much. But adding another argument to the GET does not work, in my experience - just adds a headers-hash to params, leaving the headers unchanged. – JosephK Aug 16 '19 at 06:56
4

You have to use Rack::Test::Methods#header (which delegates to Rack::Test::Session#header):

it 'правильная - get с токеном' do
  header 'X-Auth', 'some key'
  get '/offers'
  $log.debug{ "ENV was: '#{ last_request.env.keys }'" }
end
mwp
  • 8,217
  • 20
  • 26