通过 RSpec 发送自定义标头

Posted

技术标签:

【中文标题】通过 RSpec 发送自定义标头【英文标题】:Sending custom headers through RSpec 【发布时间】:2013-08-28 14:19:50 【问题描述】:

鉴于我的 API 使用者需要像这样发送客户 HTTP 标头:

# curl -H 'X-SomeHeader: 123' http://127.0.0.1:3000/api/api_call.json

然后我可以像这样在 before_filter 方法中读取此标头:

# app/controllers/api_controller.rb
class ApiController < ApplicationController
    before_filter :log_request

private
    def log_request
        logger.debug "Header: #request.env['HTTP_X_SOMEHEADER']"
        ...
    end
end

到目前为止很棒。现在我想使用 RSpec 进行测试,因为行为发生了变化:

# spec/controllers/api_controller_spec.rb
describe ApiController do
    it "should process the header" do
        @request.env['HTTP_X_SOMEHEADER'] = '123'
        get :api_call
        ...
    end
end

但是,在 ApiController 中接收到的request 将无法找到标头变量。

尝试使用带有 HTTP_ACCEPT_LANGUAGE 标头的 same code 时,它会起作用。自定义标头是否在某处过滤?

PS:网络上的一些示例使用request 而不是@request。虽然我不确定在当前的 Rails 3.2/RSpec 2.14 组合中哪一个是正确的 - 这两种方法都不会触发正确的行为,但两者都适用于 HTTP_ACCEPT_LANGUAGE

【问题讨论】:

【参考方案1】:

你可以直接在get中定义。

get :api_call, nil, 'HTTP_FOO'=>'BAR'

我刚刚验证它可以在控制台中运行。

【讨论】:

对不起 - 你的答案就在我测试的时候出现了。请查看更新。谢谢。 再次感谢 - 我也试过了,但它对我不起作用。您是否已在 RSpec 控制器规范中成功测试了这一点? 我用这个头请求,然后我请求request.env,这个头就出现了。 get 是 Rails 的 ActionDispatch::Integration::RequestHelpers 方法,而不是 Rspec。我没有在 Rspec 中这样做,但我 100% 确定它会起作用。 如前所述,我也添加了@request.env['HTTP_ACCEPT_LANGUAGE'] = 'en' - 这很有效,并且可以使用request.env 读取变量。似乎有一个我不知道的过滤器。 我认为@BillyChan 是正确的问题是你不应该从request.env 读取标题,但从request.headers api.rubyonrails.org/classes/ActionDispatch/… 自定义标题不会包含在request.env github.com/rails/rails/blob/… 【参考方案2】:

好吧,对人们来说可能为时已晚,但只是排队:

it 'should get profile when authorized' do
  user = FactoryGirl.create :user
  request.headers[EMAIL_TOKEN] = user.email
  request.headers[AUTH_TOKEN] = user.authentication_token
  get :profile
  response.should be success
end

只需使用适当的设置调用 request.headers。

【讨论】:

@request 对我来说是零 抱歉,已修复,应该没有@ request 也为零 确保你的控制器规范文件下有“render_views” 对我不起作用。我试过@request.headers['X-DeviceId'] = 'fd243cde'`(也是request...)。标头不会到达。这是在控制器规范中吗?你能读取 before_filter 中的值吗?【参考方案3】:

RSpec 请求规范 changed in Rails 5 以便现在必须使用键值哈希参数定义自定义 headersparams。例如:

Rails 4 之前:

it "creates a Widget and redirects to the Widget's page" do
  headers =  "CONTENT_TYPE" => "application/json" 
  post "/widgets", ' "widget":  "name":"My Widget"  ', headers
  expect(response).to redirect_to(assigns(:widget))
end

现在适用于 Rails 5:

it "creates a Widget and redirects to the Widget's page" do
  headers =  "CONTENT_TYPE" => "application/json" 
  post "/widgets", :params => ' "widget":  "name":"My Widget"  ', :headers => headers
  expect(response).to redirect_to(assigns(:widget))
end

【讨论】:

我的结果 - 这只是在参数中添加了一个“标题”部分。服务器接收到的标头始终是 "HTTPS"=>"off", "HTTP_HOST"=>"example.org", "HTTP_COOKIE"=>"" - 这些标头的定义位置或更改方法是未知。

以上是关于通过 RSpec 发送自定义标头的主要内容,如果未能解决你的问题,请参考以下文章

使用 CURL 发送自定义标头

发送 PHP 标头时不显示通过 Htaccess 的自定义 405 错误消息

与 qtwebkit 请求一起发送自定义标头

AngularJS ngResource 不发送自定义标头

Spring Boot 自定义授权标头请求根本没有通过

ExtJS - 使用同步时发送自定义标头