Twitter4R で & や + を含む post を送信できるようにした
Twitter4R 0.3.0 で & や + を含む文字を post できないという問題がありました。
原因を追いかけていくと twitter4r-0.3.0/lib/twitter/ext/stdlib.rb の
# Extension to Hash to create URL encoded string from key-values class Hash # Returns string formatted for HTTP URL encoded name-value pairs. # For example, # {:id => 'thomas_hardy'}.to_http_str # # => "id=thomas_hardy" # {:id => 23423, :since => Time.now}.to_http_str # # => "since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423" def to_http_str result = '' return result if self.empty? self.each do |key, val| result << "#{key}=#{URI.encode(val.to_s)}&" end result.chop # remove the last '&' character, since it can be discarded end end
の中で使われている URI.escape を & や + が通り抜けてしまうのが原因みたい。
irb(main):006:0> URI.encode("&+") => "&+"
ふむ。自分は CGI.escape を使うことが多くて、CGI.escapeならば
irb(main):008:0> CGI.escape("&+") => "%26%2B"
となって大丈夫そう。リファレンスを確認すると URI.encode でも第二引数を自分で指定すれば良いようだ。
irb(main):005:0> URI.encode("&+", /[^-_.!~*'()a-zA-Z\d;\/?:@=$,\[\]]/n) => "%26%2B"
さて、パッチを書くかと思って Contribute のページを見てtrunkを取ってこようとすると
% svn co svn://rubyforge.org/var/svn/twitter4r/trunk twitter4r svn: URL 'svn://rubyforge.org/var/svn/twitter4r/trunk' は存在しません
気を取り直して Twitter4R Retrospectiva を開くもサーバの応答が無い。というわけで、とりあえずモンキーパッチ。
require 'cgi' class Hash def to_http_str self.map{|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&") end end