@Lenciel

Tricky Bugs are tricky

最近接连遇到非常 tricky 的 bug。

首先是跟CORS有关的。话说自从 google 被墙,我们使用了 google map 或者 google font 的网站就被客户不停投诉各种打不开。本座只好去找国内可用的 CDN,居然发现360的CDN不但有常用的 jquery 库和 fontawsome 这些资源,还对 google font 做了镜像,于是就用了它。

结果用了 CDN 之后,fontawsome的图标在 firefox 下显示不正常。curl 了一下,发现 360 的基友们没有正确添加”Access-Control-Allow-Origin”的 Header:这就使得像 Firefox 这样的默认不支持 CORS 的浏览器拒绝加载不在网站自己域名下的 CORS 资源。

把 fontawsome 切换到staticfiles的CDN,问题解决了。

接下来的一个更加 tricky,我们的蔡天王在写代码的过程中发现表单被填了怪怪的内容,如下图:

Don't touch me

他检查了 js 和 html,发现这些值不是我们处理表单的时候填的,WTF?

专治各种疑难杂症的小弟拿到这个 bug,首先怀疑的是浏览器那些自动填表的插件,比如LastPass,结果用一个禁用了所有插件的 Chrome 重现了,WTF?

于是我尝试着把form和里面的input声明成autocomplete="off"的,结果仍然能重现,WTFFFF?

但是试过了几下变换表单里面的项的位置发现 bug 的行为模式是:

  1. password 这个 input 总是会被用户的密码填写
  2. password 上面那个 input 总是会被用用户的用户名填写(哪怕那个 input 是别的)

于是就感觉是 Chrome 的 password mananger 在干坏事了。google 了一下,发现这么个消息

Chrome 34 will now offer to remember and fill password fields in the presence of autocomplete=off.」 That means that if a website turns off automatic password collection, Chrome will offer to do it anyway if password manager is enabled.

古德,瓦力瓦力古德。看了如果一个网站你选择了「记住密码」,Chrome 的密码管理器就会被这个域名下包含了$('input[name=password]')的表单激活。并且它居然蠢到直接去找password上面一个 input 来填入用户名,how convenient…

要 fix 这种行为只能通过在出事的表单里面加上占位用的input来欺骗浏览器。比如我们是在 django 里面使用django-crispy-form生成表单,就可以重载它的 Layout:

    self.helper.layout =  Layout(
        HTML('<input style="display:none" type="text" name="fakeusernameremembered"/><input style="display:none" type="password" name="fakepasswordremembered"/>'),
        'name',
        'email',
        'phone',
        'qq',
        InlineCheckboxes('user_permissions'),
        'password', 'confirm_password'
    )

更多的相关信息(我希望你知道怎么翻墙),可以看看这里1,或者这里2,或者这里3

What did the ocean say to the other?

Don't touch me

最近读了张嘉佳的《从你的全世界路过》,其实就是他微博「睡前故事」的合集。

看头一两篇还行,多看几篇就发现这兄弟总是坚持不懈地出现在一段段很难自圆其说的古怪情感里面。出场的男女老少不是彪悍如风就是内向如铁,但都有一个特色就是不问过程不求结果。张兄在每个故事里面就像《红楼梦》里的癞头和尚,不是冷眼旁观抖着机灵暗透天机,就是喝着大酒爆着粗口当头棒喝。

这样的东西就好像《古惑仔》这样的电影,过程用力颓废,结尾使劲鸡汤,猛一看激荡人心,却终究是经不起回味。付出了真心的感情,既没必要过程一定要只在此山中那样晦涩沉重,更没必要结局一定要相逢一笑泯恩仇那样云淡风轻:要在恰当的时间碰到恰当的人并不容易。所谓「才下眉头,又上心头」,个中滋味只有当事人才真正明了,并没有规矩可循办法可依。

所以我决定也撸一把,睡前故事。决定了要讲故事,安排哪位先出场却让我颇费脑筋。幸亏这几天成都一直下雨,让我想起个人,他爸妈都姓李,所以他叫李叠。

李叠从小就不喜欢打伞,据说灵感来自于雨后地平线上会突然冒出的诸如竹笋、蘑菇之类的东西:这让他觉得淋雨有助于长个。这个理论按说也没错,但是没有考虑人不能倒立行走所以淋雨是不均匀灌溉的问题。于是淋雨让李叠脑袋变得比我们都大,于是这颗脑袋淋了更多的雨。循环往复,积重难返,头大的李叠走到哪里,「大头大头下雨不愁,人有雨伞我有大头」的歌谣就传唱到哪里。

某一天李叠的大头旁边多了一枚小头。姑娘话不多,每次默默地来,静静地走,但对李叠是真心好。有天李叠和我们去踢球摔了,也就擦破点儿皮。姑娘冲进宿舍给他上药,把他脏兮兮的大腿往自己腿上一横,蘸了酒精的棉签却怎么也下不去手。我们看她温柔地说了四遍,李叠你小心我要弄疼你了,终于开始操作:手到之处,李叠一颗大头上眉飞色舞锣鼓喧天,从此之后走上了踢球不要命逢踢必伤的悲壮道路。

可没多久两个人就要分开,原因他不说,我们就不问。最后一次晚饭,在他们常去的小餐馆,李叠让我们几个都去,免得场面不开心。餐馆灯光昏暗茶水粗劣,主菜京酱肉丝粗壮肥硕,既可食用亦可防身。加上厨子下手极重,感觉三两肉丝裹了三斤酱料,我们吃了一口就哭着表示不好意思今天没法提供开心的情绪了。于是姑娘缓缓起身,向我们挥手道别。

我看到李叠想伸手去握住些什么,手抬到一半,变成了挥手:「你多保重」。

姑娘咬了会儿嘴唇,对他说:「你也保重。」

没有眼泪,没有拥抱,当然也没有挽留。

不久李叠出国,跑到海的那头。收到他邮件落款成了是 Wave Li。我问他为什么搞个这么奇怪的英文名,他问我:

“Do you know what does one ocean say to the other ocean?”

“不知道。”

“Nothing, they just wave.”