<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description></description><title>tsechingho</title><generator>Tumblr (3.0; @tsechingho)</generator><link>http://blog.tsechingho.org/</link><item><title>Rails 對於行動裝置的 HTTP ACCEPT 例外處理</title><description>&lt;p&gt;最近在 hoptoad 上看到一些詭異的 log，似乎是網站升到 Rails 3 後才出現的：&lt;/p&gt;

&lt;pre&gt;
ActionView::MissingTemplate: Missing template posts/show with {:formats=&amp;gt;["application/youtube-client", "*/*"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb], :locale=&amp;gt;[:"zh-TW", :"zh-TW"]} in view paths
&lt;/pre&gt;

&lt;p&gt;沒錯，怎麼會有 format 是 &amp;#8220;application/youtube-client&amp;#8221;, &amp;#8220;&lt;em&gt;/&lt;/em&gt;&amp;#8220;，這到底是什麼鬼玩意送出來的？（狀態顯示為才疏學淺）詳細看了一下 HTTP header 資訊發現&lt;/p&gt;

&lt;pre&gt;
HTTP_ACCEPT "*/*, application/youtube-client"
HTTP_USER_AGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HD2_T8585; Windows Phone 6.5)"
HTTP_UA_OS "Windows CE (Pocket PC) - Version 5.2"
&lt;/pre&gt;

&lt;p&gt;原來是 Windows Phone 這樣的 mobile 裝置送的。&lt;/p&gt;

&lt;p&gt;但由於數量不少，於是再繼續看看是不是有其他奇怪的 log 有類似情況的：&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;居然有 PSP 的，好樣的：&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template posts/show with {:handlers=&amp;gt;[:rjs, :builder, :rhtml, :rxml, :erb], :locale=&amp;gt;[:"zh-TW", :"zh-TW"], :formats=&amp;gt;["*/*;q=0.01"]} in view paths
HTTP_ACCEPT "*/*;q=0.01"
HTTP_USER_AGENT "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)"
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;華為科技的產品，是分享器嗎？&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template photos/show with {:formats=&amp;gt;["application/vnd.wap.wmlc", "application/vnd.wap.wmlscriptc", "text/vnd.wap.wml", "image/vnd.wap.wbmp", "*/*"], :locale=&amp;gt;[:"zh-TW", :"zh-TW"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb]} in view paths
HTTP_ACCEPT "application/vnd.wap.wmlc, application/vnd.wap.wmlscriptc, text/vnd.wap.wml, image/vnd.wap.wbmp, */*"
HTTP_USER_AGENT "Mozilla/5.0 (Linux; U; Android 2.1-update1; zh-tw; MB525 Build/JRDNEM_U3_2.51.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"
HTTP_VIA "(infoX WAP Gateway), HTTP/1.1, Huawei Technologies"
HTTP_X_UP_BEAR_TYPE "WCDMA"
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;微軟的行動辦公室？&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template pages/welcome with {:formats=&amp;gt;["text/*"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb], :locale=&amp;gt;[:"zh-TW", :"zh-TW"]} in view paths
HTTP_ACCEPT "text/*"
HTTP_USER_AGENT "Microsoft Office Mobile /14.0"
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;傳說中的魔王 IE6 / Windows XP：&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template posts/show with {:formats=&amp;gt;["image/gif", "image/x-xbitmap", "image/jpeg", "image/pjpeg"], :locale=&amp;gt;[:"zh-TW", :"zh-TW"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb]} in view paths
HTTP_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg"
HTTP_USER_AGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;完全沒有 HTTP_USER_AGENT 的資訊，似乎是 POST 動作後導向失敗造成的？&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template digiphoto_posts/show with {:formats=&amp;gt;[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=&amp;gt;[:"zh-TW", :"zh-TW"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb]} in view paths
HTTP_ACCEPT "*/*"
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;同上，有正確的 format，但是呈現不同的 HTTP_ACCEPT 樣式（多筆 log 資料彙整）：&lt;/li&gt;
&lt;/ul&gt;&lt;pre&gt;
ActionView::MissingTemplate: Missing template digiphoto_posts/show with {:formats=&amp;gt;[:html], :locale=&amp;gt;[:"zh-TW", :"zh-TW"], :handlers=&amp;gt;[:rjs, :rxml, :rhtml, :builder, :erb]} in view paths
HTTP_ACCEPT "application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/msword, application/vnd.ms-excel, application/x-shockwave-flash, */*"
HTTP_ACCEPT "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
HTTP_ACCEPT "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"
HTTP_ACCEPT "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/vnd.ms-excel, */*"
&lt;/pre&gt;

&lt;p&gt;看到這樣的現象，直覺反應是，事情絕對不是想像中的那麼簡單，必定有惡魔藏在細節裡。&lt;/p&gt;

&lt;p&gt;仔細地整理一下，上述的錯誤，所要求的頁面 format 應該都要判斷為 :html 才是正確的，而其中共通的特性是 HTTP_ACCEPT 都不外乎是下列幾種：&lt;/p&gt;

&lt;pre&gt;
"*/*", "*/*;q=0.01", "text/*", "application/youtube-client", "application/vnd.wap.wmlc"
&lt;/pre&gt;

&lt;p&gt;並且似乎也跟 mobile 裝置有關，這就讓我想到有人抱怨 HTC 手機不能順利瀏覽 T 客邦網站這件事。於是乎抓了幾天的 log 來分析，居然有驚奇的發現&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/9a396c56a73b57d5ad72"&gt;https://gist.github.com/9a396c56a73b57d5ad72&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;行動裝置的 HTTP_ACCEPT 長得都不太一樣，同樣是 Android 系統，卻沒幾個能正確送出 text/html，幾乎都是送 application/xml，太令人訝異了。&lt;/p&gt;

&lt;p&gt;那 Rails 3 到底是怎麼利用 HTTP_ACCEPT 資訊，又怎麼判斷 format 的呢？&lt;/p&gt;

&lt;p&gt;直接查原始碼可以發現 ActionDispatch::Http::MimeNegotiation 有個 formats 方法，當找不到 paramater[:format] 這個傳遞資訊時，會由 HTTP_ACCEPT 猜測一個適當的 format，最後才預設為 [Mime::HTML]。（Rails 3.0.7）&lt;/p&gt;

&lt;p&gt;而這就是問題所在，猜測的邏輯沒有包含到這些狀況，上述那些怪異的 HTTP_ACCEPT，在 Rails 3.0.7 以前（含）並不能正確的處理，於是乎輕則看到這些錯誤 log，重則直接吐 502 給你。那可不妙，我可是要支援 mobile 裝置啊～&lt;/p&gt;

&lt;p&gt;幸好，活躍的 Rails 圈有人提出了問題並獲得解答：&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/6022"&gt;https://rails.lighthouseapp.com/projects/8994/tickets/6022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/5833"&gt;https://rails.lighthouseapp.com/projects/8994/tickets/5833&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;但解法目前只有 apply 在 rails master branch，我可是要解燃眉之急呀，於是自己搞了個 patch 來修補 Rails 3.0.7：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/33c10952fe3cadaec3c4"&gt;https://gist.github.com/33c10952fe3cadaec3c4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;直接抓回來放在 config/initializers 後，重新啟動 application 就行了。&lt;/p&gt;

&lt;p&gt;這個 patch 同時解決了兩件事：&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;針對特殊的 HTTP_ACCEPT，如 &amp;#8220;&lt;em&gt;/&lt;/em&gt;&amp;#8221;, &amp;#8220;&lt;em&gt;/&lt;/em&gt;;q=0.01&amp;#8221;, &amp;#8220;text/*&amp;#8221; 都能正確判斷 format 是 [Mime::JS] 或 [Mime::HTML]。&lt;/li&gt;
&lt;li&gt;針對行動裝置送的 application/xxx 這類型 HTTP_ACCEPT 也能返回正確的 Mime::SET。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如此一來就能好好面對行動裝置的挑戰了。&lt;/p&gt;</description><link>http://blog.tsechingho.org/post/5385396627</link><guid>http://blog.tsechingho.org/post/5385396627</guid><pubDate>Wed, 11 May 2011 14:48:35 +0800</pubDate></item></channel></rss>

