<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>bianjp (Bian Jiaping)</title>
    <link>https://ruby-china.org/bianjp</link>
    <description>得即高歌失即休，多愁多恨亦悠悠。</description>
    <language>en-us</language>
    <item>
      <title>Rails 5 + guard-livereload 不能热更新 CSS 的解决方案</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/guard/guard-livereload" rel="nofollow" target="_blank" title=""&gt;guard-livereload&lt;/a&gt; 是个非常棒的工具，做前端开发时会非常方便：修改 view, Javascript 后自动刷新页面，修改 CSS 后热更新 CSS 而不刷新整个页面。&lt;/p&gt;

&lt;p&gt;但最近在 Rails 5.0.1 下使用时却不能热更新 CSS 了。加载新 CSS 文件的请求，Rails 竟返回 404：
&lt;img src="https://l.ruby-china.com/photo/2017/4780025a1de886e2806fcb3e899f5167.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;搜索了一下，有人已给 guard-livereload 提了个 &lt;a href="https://github.com/guard/guard-livereload/issues/169" rel="nofollow" target="_blank" title=""&gt;issue&lt;/a&gt;，但并没有人提出解决方案，只好自己动手排查了。&lt;/p&gt;

&lt;p&gt;过程就不细说了，主要是深入 Rails/Sprockets 的源代码找到处理 assets 请求的代码，粗暴地在 gem 安装目录（ &lt;code&gt;~/.gem/&lt;/code&gt;）下直接修改 sprockets 的代码，输出一些变量的状态以辅助理解代码。&lt;/p&gt;
&lt;h2 id="原因"&gt;原因&lt;/h2&gt;
&lt;p&gt;多个原因共同导致 asset 请求返回 404：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;livereload 在热更新 CSS 时，只在原 URL 的查询字符串中加了个时间戳，并没有更新 URL 中的 digest&lt;/li&gt;
&lt;li&gt;Sprockets 会验证 URL 中的 digest 与实际的 digest 是否一致，不一致就返回 404&lt;/li&gt;
&lt;li&gt;Rails 4.2 生产的 asset URL 中包含 "?body=1"，Spockets 为了兼容 2.x 版本，看到 "?body=1" 就会跳过 digest 验证&lt;/li&gt;
&lt;li&gt;但 Rails 5 生成的 asset URL 中不包含 "?body=1" 了。同时 Sprockets 4.0.0 beta 也删掉了兼容 2.x 版本的代码，不能再通过 "?body=1" 禁止 digest 验证了。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="解决方案"&gt;解决方案&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;config/environments/development.rb&lt;/code&gt; 中加入或修改&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config.assets.digest = false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以禁止在 URL 中包含 digest，从而绕过 Sprockets 的 digest 验证。&lt;/p&gt;

&lt;p&gt;我在原 &lt;a href="https://github.com/guard/guard-livereload/issues/169" rel="nofollow" target="_blank" title=""&gt;issue&lt;/a&gt; 中也贴出了解决方案，欢迎围观。&lt;img title=":grinning:" alt="😀" src="https://twemoji.ruby-china.com/2/svg/1f600.svg" class="twemoji"&gt;&lt;/p&gt;</description>
      <author>bianjp</author>
      <pubDate>Wed, 18 Jan 2017 23:11:30 +0800</pubDate>
      <link>https://ruby-china.org/topics/32169</link>
      <guid>https://ruby-china.org/topics/32169</guid>
    </item>
    <item>
      <title>第一次给 Rails 做了点小贡献：修复 rake guides:generate:kindle 任务</title>
      <description>&lt;p&gt;最近想在 Kindle 上看 Rails guides，查了下，发现 Rails 提供了 rake 任务 &lt;code&gt;guides:generate:kindle&lt;/code&gt;，太棒了~&lt;/p&gt;

&lt;p&gt;可是执行的时候却总是提示要安装 &lt;a href="https://github.com/danchoi/kindlerb" rel="nofollow" target="_blank" title=""&gt;kindlerb&lt;/a&gt;，明明已经安装了啊！一番探查，发现原来是有人曾提 PR 把 kindlerb 从 0.1.1 升级到了 1.0.1，也没人仔细测试就合并了。然而 kindlerb 1.0 有个 breaking change：原先要通过命令 &lt;code&gt;kindlerb&lt;/code&gt; 调用，现在只能通过 Ruby 接口 &lt;code&gt;Kindlerb.run&lt;/code&gt; 调用。&lt;/p&gt;

&lt;p&gt;于是给 Rails 提了个 &lt;a href="https://github.com/rails/rails/pull/27396" rel="nofollow" target="_blank" title=""&gt;PR&lt;/a&gt; 修复了这个问题。&lt;/p&gt;

&lt;p&gt;另外，也给 kindlerb 提了个 &lt;a href="https://github.com/danchoi/kindlerb/pull/7" rel="nofollow" target="_blank" title=""&gt;PR&lt;/a&gt;，主要是增加使用系统安装的 kindlegen 的支持（我大 Arch 能方便地安装 &lt;a href="https://aur.archlinux.org/packages/kindlegen/" rel="nofollow" target="_blank" title=""&gt;kindlegen&lt;/a&gt; 就不用你代劳了&lt;img title=":grinning:" alt="😀" src="https://twemoji.ruby-china.com/2/svg/1f600.svg" class="twemoji"&gt; ），同时提供一个接口用于检查 kindlegen 是否已安装。&lt;/p&gt;</description>
      <author>bianjp</author>
      <pubDate>Sun, 18 Dec 2016 23:41:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/31930</link>
      <guid>https://ruby-china.org/topics/31930</guid>
    </item>
    <item>
      <title>注意 I18n.locale 是 thread-local</title>
      <description>&lt;p&gt;公司某个项目要做多语言支持了，由于我不确定 &lt;code&gt;I18n.locale&lt;/code&gt; 是不是全局变量，所以查了下源代码，发现 &lt;code&gt;I18n.locale&lt;/code&gt; 是保存在 thread-local variable 中的：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sets the current locale pseudo-globally, i.e. in the Thread.current hash.&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enforce_available_locales!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reference：&lt;a href="https://github.com/svenfuchs/i18n/blob/v0.7.0/lib/i18n/config.rb#L11" rel="nofollow" target="_blank"&gt;https://github.com/svenfuchs/i18n/blob/v0.7.0/lib/i18n/config.rb#L11&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="为什么不使用全局变量？"&gt;为什么不使用全局变量？&lt;/h4&gt;
&lt;p&gt;大概是为了在多线程环境（比如 puma）中避免请求之间相互影响。&lt;/p&gt;

&lt;p&gt;多线程环境下，多个请求是可以并行被不同线程处理的，若使用全局变量，一个请求中修改了 &lt;code&gt;I18n.locale&lt;/code&gt;，其它线程正在处理的请求也会受影响。&lt;/p&gt;
&lt;h4 id="有什么影响？"&gt;有什么影响？&lt;/h4&gt;
&lt;p&gt;1. 若在一个请求中修改了 &lt;code&gt;I18n.locale&lt;/code&gt;，&lt;strong&gt;其它线程的后续请求不会受影响，当前线程的后续请求可能会受影响&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;若每个请求中都明确设置了 &lt;code&gt;I18n.locale&lt;/code&gt;，则不受影响&lt;/li&gt;
&lt;li&gt;若后续的请求没有设置 &lt;code&gt;I18n.locale&lt;/code&gt;，那么 &lt;code&gt;I18n.locale&lt;/code&gt; 的值不是配置文件中配置的默认值，而是之前的请求设置的值&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;然而请求一般是被随机的分配给各个线程处理的，所以很难说哪个请求会受影响。&lt;/p&gt;

&lt;p&gt;2. 设置 &lt;code&gt;I18n.locale&lt;/code&gt; 后，各处都可放心地使用 &lt;code&gt;I18n.locale&lt;/code&gt;。比如在 Model 中给属性加个 wrapper 方法，根据语言返回相应的字段&lt;/p&gt;
&lt;h4 id="结论"&gt;结论&lt;/h4&gt;
&lt;p&gt;若要在 controller 中设置 &lt;code&gt;I18n.locale&lt;/code&gt;，各种条件下都要明确设置 &lt;code&gt;I18n.locale&lt;/code&gt;，不要只在满足某些条件时才设置。&lt;/p&gt;</description>
      <author>bianjp</author>
      <pubDate>Mon, 05 Dec 2016 12:02:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/31799</link>
      <guid>https://ruby-china.org/topics/31799</guid>
    </item>
    <item>
      <title>Mozilla, Google, Apple 都已决定不再信任 WoSign 和 StartCom</title>
      <description>&lt;p&gt;由于 WoSign（沃通）和 StartCom 存在的&lt;a href="https://wiki.mozilla.org/CA:WoSign_Issues" rel="nofollow" target="_blank" title=""&gt;一系列技术和管理上的问题&lt;/a&gt;，Mozilla, Google, Apple 都已决定不再信任 WoSign 和 StarCom 新颁发的证书了。就差 Microsoft 没行动了，不过大势已定，Microsoft 怎么行动已经不太重要了。&lt;/p&gt;

&lt;p&gt;各方的决定不尽相同：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mozilla: &lt;a href="https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/" rel="nofollow" target="_blank"&gt;https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google: &lt;a href="https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html" rel="nofollow" target="_blank"&gt;https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Apple: &lt;a href="https://support.apple.com/en-us/HT204132" rel="nofollow" target="_blank"&gt;https://support.apple.com/en-us/HT204132&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mozilla:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;从 Firefox 51（预计 2017-01-24 发布）开始，不再信任 WoSign 和 StartCom 2016 年 10 月 21 日 后颁发的证书。&lt;/li&gt;
&lt;li&gt;不再信任之前已经查明的倒填日期的 SHA-1 证书。&lt;/li&gt;
&lt;li&gt;要是再发现倒填日期，立即永久取消信任涉及到的根证书。倒是没说取消信任公司。&lt;/li&gt;
&lt;li&gt;不再信任给 WoSign 做安全审计的安永会计师事务所（香港）的审计报告。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;从 Chrome 56（预计 2017-01-31 发布）开始，不再信任 WoSign 和 StartCom 2016 年 10 月 21 日 后颁发的证书。&lt;/li&gt;
&lt;li&gt;之前颁发的证书会信任，但不一定都信任，似乎是采用&lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=661003" rel="nofollow" target="_blank" title=""&gt;白名单策略&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;如果 WoSign 和 StartCom 试图规避这些措施，立即完全取消信任&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;取消信任 WoSign CA Free SSL Certificate G2 这一个中间证书。用其它根证书签发的免费证书、付费证书都不受影响。&lt;/li&gt;
&lt;li&gt;2016-09-19 及之前签发的且记录到 Certificate Transparency log servers 的证书会继续信任&lt;/li&gt;
&lt;li&gt;没对 StartCom 采取任何行动&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;总的来说，2016-09-19 之后签发的免费证书、2016-10-21 之后签发的所有证书都不会被信任，之前签发的也只有记录到了 Certficate Transparency 的才会被继续信任。&lt;/p&gt;

&lt;p&gt;证书是否记录到了 Certficate Transparency 可以在 &lt;a href="https://crt.sh/" rel="nofollow" target="_blank"&gt;https://crt.sh/&lt;/a&gt; 查询。&lt;/p&gt;</description>
      <author>bianjp</author>
      <pubDate>Tue, 01 Nov 2016 20:56:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/31494</link>
      <guid>https://ruby-china.org/topics/31494</guid>
    </item>
  </channel>
</rss>
