Rails開発を行っていますが、標記の2つを組み合わせると思わぬ挙動となってしまいました。
escape_utilsとは
RailsのようなWebアプリでは、あちこちで文字列のエスケープ処理が必要となりますが、基本的にはRuby内部で正規表現マッチにより行っています。brianmario/escape_utilsは、そのような定型的なエスケープ処理をC言語で行うことで、数十倍に高速化するためのgemです。
使い方
読み込んだだけでは適用されないので、config/initializers/
以下でモンキーパッチを適用する必要があります。
begin
######### あとで解説します
EscapeUtils.html_secure = false
######### 今回の記事のポイント
require 'escape_utils/html/rack' # to patch Rack::Utils
require 'escape_utils/html/erb' # to patch ERB::Util
require 'escape_utils/html/cgi' # to patch CGI
require 'escape_utils/html/haml' # to patch Haml::Helpers
# for patches in Rails 4.2 ActiveSupport
if ActiveSupport.version.to_s.start_with?('4.')
module ActiveSupport
class SafeBuffer # :nodoc:
private
def html_escape_interpolated_argument(arg)
return arg if !html_safe? || arg.html_safe?
CGI.escapeHTML(arg.to_s)
end
end
end
class ERB
module Util # :nodoc:
def unwrapped_html_escape(s) # :nodoc:
s = s.to_s
if s.html_safe?
s
else
CGI.escapeHTML(s)
end
end
singleton_class.__send__(:remove_method, :unwrapped_html_escape)
module_function :unwrapped_html_escape
end
end
end
rescue LoadError
Rails.logger.info 'Escape_utils is not in the gemfile'
end
なお、Rails 4では一部のルーチンについて自前実装しているので、別個でモンキーパッチをかける必要がありました(if
文を見ての通り、Rails 5の場合には不要です)。
web-console
Rails開発者にはもはや説明不要かもしれませんが、Web上でRailsのコンソールにアクセスできるという、開発には欠かせない一品です(rails/web-console)。
2つ組み合わせてみると
開発環境でこの2つを合わせて使っていたのですが、コンソールに何を打ち込んでもuntranslated ja.errors.unacceptable_request
のようなメッセージが出るようになってしまいました。
Chromeのほうのコンソールを開いて追いかけてみると、web consoleが投げたリクエストに406を返していました。ヘッダを見てみると、Accept: application.vnd.web-console.v2
と、実体参照をそのまま投げていました。
答え合わせ
実際に吐かれたJavaScript上で実体参照となってしまった箇所のソースを探してみると、/lib/web_console/templates/console.js.erb
の中にありました(リンク)。そして、ふつうであればスラッシュのエスケープはされないところ、escape_utilsが気を利かせてスラッシュまでエスケープしてくれるために、ここまでエンコードされてしまった、ということでした。
これがweb-console側でIssuになるかはわからないですが(標準状態では問題にならないので)、とりあえずモンキーパッチ前にEscapeUtils.html_secure = false
として、スラッシュのエスケープを止めることで、とりあえず動くようになりました。