安装Rails 4.0 beta
感觉Rack::Builder就是个奇怪的存在

A bug fix for Rails 2.3 Stable: 关于测试环境下有时不能正确写入Cookie的问题

bachue posted @ 2013年3月10日 00:34 in Ruby with tags ActiveController Cookie rails ruby test vim RubyMine , 3790 阅读

最近在帮我们最大的一个Rails项目(多大?想象下上万行Ruby代码的项目吧)做Rails升级,从2.3.2升级到2.3.17(别笑,这种项目升3是没有指望的),升级过程总体上顺利。升级完后跑Test Case,有一些小错误发生。一个小错误似乎是由于Rails 2.3.2存在Bug使得明明应该发生错误的Test Case竟然能通过,而在2.3.17的时候已经修复,导致这个Test Case理所当然的发生了错误。还有另外一个错误是在测试中向response header中写入了被标记为secure和httponly的cookie,但是测试发现这些cookie不存在的错误。起先我还不以为然,以为是redirect后造成cookie在测试时不能正常读取,但是后来总觉得有点奇怪,毕竟这个Test Case在2.3.2的时候是通过的,还有就是调试发现,在执行好redirect_to方法后,被写入的cookie依然是存在的,只有当请求结束后的测试时cookie才会消失。太诡异了!于是仔细跟踪代码流,并对比了下2.3.2和2.3.17的区别,发现了在2.3.17的actionpack/lib/action_controller/cookies.rb中的CookieJar类(这个是存储Cookie的最核心的数据结构了,继承自Hash)的[]=方法中,在向response header写入cookie前,调用了下一个叫做write_cookie?的方法,这个方法在2.3.2中是不存在的。代码如下:

# Sets the cookie named +name+. The second argument may be the very cookie
# value, or a hash of options as documented above.
def []=(key, options)
  if options.is_a?(Hash)
    options.symbolize_keys!
  else
    options = { :value => options }
  end

  options[:path] = "/" unless options.has_key?(:path)
  super(key.to_s, options[:value])
  @controller.response.set_cookie(key, options) if write_cookie?(options)
end

从代码中可以看到,write_cookie?方法并不阻止super的调用,但是阻止了set_cookie的调用。而通过调试可知,在测试时这个write_cookie?这个方法的的确确返回了false,造成了cookie在测试时没有正常写入!

而这个问题的始作俑者,write_cookie?的代码是这样的:

def write_cookie?(cookie)
  @secure || !cookie[:secure] || defined?(Rails.env) && Rails.env.development?
  # 其中@secure来自initialize时controller.request.ssl?的结果
end

在测试过程中,三个条件均为false,导致最终结果是false。

由于这个站点的安全级别较高,在生产环境中一定是用HTTPS协议运行的,所以在测试的时候也模拟HTTPS的环境,在cookie中写入了secure标志并在测试中有相应的assert。在2.3.2中,由于没有这个方法的存在,测试没有任何问题。但是在2.3.17中,明确要求了,要么cookie是被设置成secure的,要么必须是https请求,要么当前是development模式。但是在我们的测试中,我们并没有让所有测试都用https来做,这也是不合理的嘛。因此我认为,在这段代码中,Rails犯了三个错误,第一,应该把Rails.env.test?也加入或条件,即如果是测试环境,也总会让write_cookie?返回true。第二,如果write_cookie?返回false,super方法也不应当调用,不该造成cookie已经被写入的假象。第三,后台应该有安全警告,以说明本次cookie写入失败的原因,否则对开发者而言实在是莫名其妙。

本来想给Rails提交个patch的,但是得知Rails 2.3除了Fix严重安全漏洞以外不再接受任何Patch了(链接),因此还是写成Blog让大家看到吧。我最后在项目中加了这个一个Monkey Patch:

# The write_cookie? always returns false in our test cases because 
# we set secure in cookie and our request in test env is http 
# rather than https, so Rails will refuse to write value in cookie. 
# This hack will resolve this problem. 
class ActionController::CookieJar < Hash
  alias_method :__origin_write_cookie?, :write_cookie?
  def write_cookie?(cookie)
    __origin_write_cookie?(cookie) || defined?(Rails.env) && Rails.env.test?
  end
end

解决掉了这个问题。至于另外两点就懒得用Monkey Patch做了,还是算了吧。

就这样了。由此可见,Rails程序员熟悉Rails本身的代码是很重要的吧,仅仅局限在使用Rails框架上实在是太肤浅了,根本对不起四年大学本科的学习嘛,何况Rails这种项目由于是开源的本来就问问多多嘛,不熟悉的话稍微有点什么问题就束手无策了。我们组有些同事就是这样的,拿了个比VIM先进的多的RubyMine,叫他调试下出错的Test Case就各种震惊各种迷茫的,实在是,哎,不说了,说出来比我自己干还累啊。。

Patna Board Inter Qu 说:
2022年8月22日 00:17

We advise any test-takers who wish to examine their Bihar intermediate Question Paper 2023 to use the Bihar Board 11th Model Paper with Answers. Download sample test questions for the arts History The study of politics Sociology Philosophy economy, psychology, and geography Domestic Science Commerce Sample Exam Papers Accountancy Economics, Business, Entrepreneurship, and Humanities Sample Test Questions Spanish Hindi Literature and Language English Urdu Science Model Question Papers from Maithilli Chemistry Biology Physics Patna Board Inter Question Paper 2023 Mathematics Patna Board Inter Question Paper 2023, BSEB 11th Model Paper 2023 On this website, we offer tips and information on how students may prepare for exams. Important Question Paper 2023 from Patna Board. Get your Patna Board Inter 11th Class Important Question Paper 2023 by simply following the instructions.

civaget 说:
2024年1月17日 21:52

The skilled therapists at 오피타임 make all the difference.

civaget 说:
2024年1月18日 05:09

제주안마 is a natural way to detoxify your body while enjoying the beauty of Jeju Island, making it an excellent choice for holistic wellness.

seo service london 说:
2024年2月22日 19:28

true happiness can be difficult to achieve, you can be rich but still not be truly happy


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter