標籤:Rails

Rails API 送了 `Accept: application/json, */*` 拿到 406

之前在 Rails API mode 遇到 Client 在 Header 送了 Accept: application/json, text/html, */* 結果拿到 406 的問題,原先以為是 Client 送法不對(Server 只吃 JSON)。

查了一下 RFC2616 發現這樣的送法應該沒有什麼問題才對:

If an Accept header field is present, and if the server cannot send a response which is acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response.

Server 應該在能夠回傳任一指定 Accept type 時回傳指定 Type,如果都不能夠回傳時才 406,尤其 Client 還用了 */*,應該是要無論如何都不會 406 才對……

詳細查了一下發現1,Rails 會將 Client 送出多個 Mime type 搭配上 */*(例如:Accept: x-any-type/x-any-subtype, */*Accept: */*, x-any-type/x-any-subtype)的行為認為是 Browser 預設行為(據說是老 IE)而強制在 ActionDispatch 複寫成 HTML type。

但是 API mode 的 Rails 本來就不可能返回 HTML,結果就導致 Server 噴 406……
解法也很簡單,就是把判斷用部分蓋掉就好,這裡選擇把 Regexp 複寫掉:

ActionDispatch::Http::MimeNegotiation.send :remove_const, :BROWSER_LIKE_ACCEPTS
ActionDispatch::Http::MimeNegotiation.const_set :BROWSER_LIKE_ACCEPTS, /NEVER_MATCHED_MIME_TYPE_LOL/

[筆記] ERubies 在 Rails 做的事情

因為小畢在 Slack 上面對 SanitizeHelper 發問,所以就順手找了一下 Erb 在 Rails 中是怎麼處理 render 的(包含 html_safe? 之類的判斷),才發現 ERuby 是一個大 compiler …… 負責把 HTML + embedded ruby compile 成 ruby code,而且其實還有 ERubies 在後面把專案做大,現在有 EC、EPHP、EJava……等 compiler 了。