ruby-fcgi (FastCGI library for Ruby) を C バージョンでインストールするには

Fast CGI Development Kit をインストール http://www.fastcgi.com の「API/Libraries」のThe Development Kit - C, C++, Perl, and Java, libraries as well as assorted documentation.の Current Download から fcgi.tar.gz をダウンロードする。普通にコンパイル・インストール。 $ wget http://www.fastcgi.com/dist/fcgi.tar.gz $ tar zxvf fcgi-2.4.0.tar.gz $ cd fcgi-2.4.0 $ ./configure $ make # make install ruby-fcgi をインストール http://rubyforge.org/frs/?group_id=926 から ruby-fcgi-0.8.7.tar.gz をインストールする。C バージョンで config を行うのに、README のとおり一般ユーザーで ruby install.rb config したら上手くいかなかった。 $ wget http://rubyforge.org/frs/download.php/11368/ruby-fcgi-0.8.7.tar.gz $ tar zxvf ruby-fcgi-0.8.7.tar.gz $ cd ruby-fcgi-0.8.7 # ruby install.rb config – –with-fcgi-include=/usr/local/include –with-fcgi-lib=/usr/local/lib # ruby install.rb setup # ruby install.rb install

2008年12月3日 · Toshimitsu Takahashi

モバイルサイト用のヘッダ出力を Ruby で書いてみた

モバイルサイト用のヘッダ出力を Python で書いてみた - Tosshi Note モバイルサイトを3キャリアでほぼ共通化して作りたい - http://d.hatena.ne.jp/tilfin/20080530/1212376626 上記のエントリで DoCoMo, au, SoftBank 用のモバイルサイトを XHTML で作成する場合のそれぞれの書き方を調べた。 その書き方に従って HTTP ヘッダと XHTML 宣言部分を出力する CGI サンプルを Python で書いてみた。 で書いたスクリプトを今度は Ruby で書いてみました。 require ‘kconv’ class UserAgent def initialize(ua) if ua.nil? @kind = 0 elsif ua.match(/^DoCoMo/) @kind = 1 elsif ua.match(/^KDDI/) @kind = 2 elsif ua.match(/^SoftBank|Vodafone|MOT/) @kind = 3 else @kind = 0 end end def is_mobile return @kind > 0 end def is_docomo return @kind == 1 end def is_au return @kind == 2 end def is_softbank return @kind == 3 end def get_content_type if @kind > 0 return “Content-Type:application/xhtml+xml; charset=Shift_JIS” else return “Content-Type:text/html; charset=UTF-8” end end def get_declare if @kind == 1 return «EOF ...

2008年7月10日 · Toshimitsu Takahashi

Ruby で CSS のカラー指定を RGB 値の配列に変換する

スタイルシートのカラー指定文字列を 3 要素の RGB 値の配列として取得する方法のメモ書き。逆変換のメソッドもあり。 css.rb # # Ruby CSS Color Module # module ColorUtil def get_rgb(value) if value =~ /^#?(\[a-fA-F0-9\]+)$/ c = $1 if c.length == 3 return Array.new(3) { |i| (c\[i,1\] \* 2).hex } elsif c.length == 6 return \[ c\[0,2\].hex, c\[2,2\].hex, c\[4,2\].hex \] end end raise "format error" end def get_value(rgb) c = "#" rgb.each { |x| c += format("%02x", x) } return c end end サンプル $ irb irb(main):001:0> require 'css' =\> true irb(main):002:0> include ColorUtil =\> Object irb(main):003:0> get_rgb("000") =\> \[0, 0, 0\] irb(main):004:0> get_rgb("#00ddff)" irb(main):005:1> ) =\> nil irb(main):006:0> get_rgb("#00ddff") =\> \[0, 221, 255\] irb(main):007:0> get_rgb("#999") =\> \[153, 153, 153\] irb(main):008:0> get_value(\[153,153,153\]) =\> "#999999" irb(main):009:0> get_value(\[255, 255, 0\]) =\> "#ffff00"

2008年6月12日 · Toshimitsu Takahashi

Ruby net/http で Web サービスが動いているか確認する

Web サービスが停止していないかどうか確認するスクリプト。 open-uri を使うとタイムアウトが設定できないので、net/http で行う。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #!/usr/bin/env ruby require 'net/http' PROXY_ADDRESS = nil \# プロキシサーバのアドレス PROXY_PORT = nil \# プロキシサーバのポート def check\_site\_alive(domain, port = 80) begin Net::HTTP.start(domain, port, PROXY_ADDRESS, PROXY_PORT) do |http| http.open_timeout = 20 http.read_timeout = 40 \# ↓は Web サービスにあわせて書き換える response = http.post(path, data) return response.code == '200' end rescue Exception =\> e puts e return false end end puts check\_site\_alive("webservice.domain")

2008年3月2日 · Toshimitsu Takahashi

Ruby CGI::Session で Cookie が発行されない

ログイン CGI でクッキーがクライアントに返らないので調べたら・・・ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #!/usr/bin/env ruby require 'cgi/session' …(省略)… def create_session(cgi, timeout) begin \# 既存のセッションは削除 session = CGI::Session.new(cgi, { 'new_session' =\> false }) session.delete rescue ArgumentError end return CGI::Session.new(cgi, { 'new_session' =\> true, 'session_expires' =\> timeout }) end end session = create_session(cgi, Time.now + 3600) session\['savadata'\] = "hogehoge" print "Content-Type:text/html\\r\\n\\r\\n" print <<EOF <html> <body> <p>login success.</p> </body> </html> EOF exit 0 としたらクッキーができない。 ヘッダの出力がないことに気づいた。 ...

2008年2月29日 · Toshimitsu Takahashi

Ruby/LDAP を使って LDAP からユーザーとその所属グループのリストを生成する

Ruby/LDAP を使う。Ruby/LDAP People からユーザとそのメイングループ番号を gidNumber から取得する。 各ユーザーのメイングループの cn を取得する。 グループを全て走査して、所属するユーザーにマップをグループに追加する。 「user:group1,group2」という形式で書き出す。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #!/usr/bin/env ruby require 'ldap' people = Hash.new LDAP::SSLConn.new("ldap.company.com") do |conn| conn.set_option(LDAP::LDAP\_OPT\_PROTOCOL_VERSION,3) bind_conn = conn.bind(バインドユーザのDN, バインドユーザのパスワード) bind_conn.search2("ou=People,dc=company,dc=com", LDAP::LDAP\_SCOPE\_SUBTREE, "uidNumber=*", \['uid', 'gidNumber'\]) { |entry| uid = entry\['uid'\].first gid = entry\['gidNumber'\].first people.store(uid, gid) } people.each do |k, v| bind_conn.search2("ou=Group,dc=company,dc=com", LDAP::LDAP\_SCOPE\_SUBTREE, "gidNumber=#{v}", \['cn'\]) { |entry| cn = entry\['cn'\].first people.store(k, \[cn\]) } end groups = Array.new bind_conn.search2("ou=Group,dc=company,dc=com", LDAP::LDAP\_SCOPE\_SUBTREE, "gidNumber=*", \['dn'\]) { |entry| entry\['dn'\].each { |e| groups.push e } } groups.each do |group| bind_conn.search2(group, LDAP::LDAP\_SCOPE\_SUBTREE, "(objectClass=*)", \['cn', 'memberUid'\]) { |entry| cn = entry\['cn'\].first uids = entry\['memberUid'\] next if uids.nil? uids = \[uids\] unless uids.is_a?(Array) uids.each { |uid| if people.key? uid people\[uid\].push(cn) end } } end end people.each do |uid, groups| print "#{uid}:" puts groups.join(",") end

2008年2月6日 · Toshimitsu Takahashi

Ruby で PDF を出力する CGI

pdffile のパスにある PDF を読みつつ吐き出す CGI のサンプル #!/usr/bin/env ruby pdffile = “sample.pdf” print “Content-Type:application/pdf\r\n” print “Content-Length: #{File.size(pdffile)}\r\n” print “\r\n” open(pdffile, “rb”) { |f| while buf = f.gets do print buf end }

2008年1月25日 · Toshimitsu Takahashi

Ruby で Premature end of script headers

CGI を作っていて、Premature end of script headers が全然消えない。 print ‘Content-Type:text/html\r\n\r\n’ ってシングルクォートで囲うと、\r\nが特殊文字ではなくそのままに認識されるのでした。 print “Content-Type:text/html\r\n\r\n” でないとダメ。 あと、require しているライブラリへのパーミッションがなかったりしても Premature end of script headers が起きる。 気づきにくかったのは popen での Broken Pipe エラー、これは呼び出していたスクリプトの実行権限がなかった。

2008年1月18日 · Toshimitsu Takahashi

REXML と Libxml-Ruby とのエンティティ出力比較

REXML で大きな XML ファイルを処理したらあまりにも遅かった。Ruby で書かれているのでいたし方ないんですが。もちろん REXML は標準でついているし、手軽に使えて良いという大きなメリットがあるけど、行う処理が数時間レベルなので速くしたい。そこで Libxml http://libxml.rubyforge.org/ を試すことに。 行うのは XML → XML 変換なので、エンティティの出力が気になった。そこで次のようなコードを実行して、結果を比較してみる。 テストしたコード 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #!/usr/bin/env ruby # require 'rubygems' require 'xml/libxml' require 'rexml/document' str =<<EOS <?xml version="1.0" encoding="UTF-8"?> <root> <title>Tosshi&apos;s メモ書き</title> <array> <item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item> <item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item> </array> </root> EOS puts <<EOS \[ libxml-ruby \] EOS xp = XML::Parser.new xp.string = str libxmldoc = xp.parse puts "document :" puts libxmldoc node = libxmldoc.root.find_first("title") print "Node :" puts node print "content :" puts node.content print "child.to_s:" puts node.child.to_s libxmldoc.root.find("array/item").each do |item| print "Node :" puts item print "content :" puts item.content print "child.to_s:" puts item.child.to_s end puts <<EOS \[ REXML \] EOS rexmldoc = REXML::Document.new(str) puts "Document :" puts rexmldoc el = rexmldoc.root.elements\["title"\] print "Element :" puts el print "text :" puts el.text print "get_text :" puts el.get_text rexmldoc.root.elements.each("array/item") do |item| print "Element :" puts item print "text :" puts item.text print "get_text :" puts item.get_text end 結果 libxml はアポストロフィとダブルクォートを必要なときだけ実体名にエスケープする。 REXML は属性値は固定でアポストロフィで囲い、アポストロフィとダブルクォートは必ず実体名にエスケープする。 $ ruby testxml.rb \[ libxml-ruby \] Document : <?xml version="1.0" encoding="UTF-8"?> <root> <title>Tosshi's メモ書き</title> <array> <item attr="'"> &lt;html&gt; 'TAG" </item> <item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item> </array> </root> Node :<title>Tosshi's メモ書き</title> content :Tosshi's メモ書き child.to_s:Tosshi's メモ書き Node :<item attr="'"> &lt;html&gt; 'TAG" </item> content : <html> 'TAG" child.to_s: &lt;html&gt; 'TAG" Node :<item attr="&quot;"><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item> content : CDATA &lt;html&gt; &apos;TAG&qout; <>"' child.to_s:<!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]> \[ REXML \] Document : <?xml version='1.0' encoding='UTF-8'?> <root> <title>Tosshi&apos;s メモ書き</title> <array> <item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item> <item attr='&quot;'><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item> </array> </root> Element :<title>Tosshi&apos;s メモ書き</title> text :Tosshi's メモ書き get_text :Tosshi&apos;s メモ書き Element :<item attr='&apos;'> &lt;html&gt; &apos;TAG&quot; </item> text : <html> 'TAG" get_text : &lt;html&gt; &apos;TAG&quot; Element :<item attr='&quot;'><!\[CDATA\[ CDATA &lt;html&gt; &apos;TAG&qout; <>"' \]\]></item> text : CDATA &lt;html&gt; &apos;TAG&qout; <>"' get_text : CDATA &lt;html&gt; &apos;TAG&qout; <>"'

2008年1月11日 · Toshimitsu Takahashi

Ruby の REXML と RSS Maker で Amazon で売れてるオライリー本のフィードを簡単に作る

使用したライブラリ open-uri rexml/document rss/maker RSS Parser ※ We retire raa.ruby-lang.org という Amazon Web Service を簡単に使えるライブラリも存在するが、単にリストを取得するだけなので今回は見送った。 コード RSS 2.0 で出力する。RSS::Maker.make(version) で引数にバージョンを入れて指定する。 Description にイメージと著者、出版日、価格を入れている。Author は複数タグあるため、カンマで結合。 同じようなものを仕事で Java で作ったことがあったが、Ruby などの Light Weight 言語の手軽さを知ってしまうと戻れない。 結果: http://feed.tilfin.net/amazon/oreilly-bestseller.xml 下記のコードでは、ファイル書き出しをコメントアウトして、CGIとしての動作を有効にさせている。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #!/usr/bin/env ruby # # Amazon O'Relly Sales Ranking # Rss feed # ################################# require 'open-uri' require 'rexml/document' require 'rss/maker' param = { 'Service' => 'AWSECommerceService', 'AWSAccessKeyId' => '☆アクセスキーID☆', 'AssociateTag' => '☆アソシエイトID☆', 'Operation' => 'ItemSearch', 'SearchIndex' => 'Books', 'ResponseGroup' => 'Medium', 'Sort' => 'salesrank', 'Publisher' => 'オライリー' } params = param.map do |key, value| "#{URI.encode(key)}=#{URI.encode(value)}" end.join("&") doc = nil open('http://webservices.amazon.co.jp/onca/xml?' \+ params) { |resp| doc = REXML::Document.new(resp) } rss = RSS::Maker.make("2.0") do |maker| maker.channel.title = "O'Reilly ベストセラー (Amazon)" maker.channel.description = "O'Reilly の Amazon.co.jp のセールストップ 10 を紹介" maker.channel.link = "http://feed.tilfin.net/amazon/orelly-bestseller.xml" number = 0 doc.elements.each("/ItemSearchResponse/Items/Item") do |item| itmat = item.elements\["ItemAttributes"\] number += 1 entry = maker.items.new_item entry.title = number.to_s + '. ' \+ itmat.elements\["Title"\].text entry.link = item.elements\["DetailPageURL"\].text desc = nil item.elements.each("MediumImage") { |img| desc = <<EOS <img src="#{img.elements\["URL"\].text}" width="#{img.elements\["Width"\].text}" height="#{img.elements\["Height"\].text}"><br> EOS } desc += itmat.elements.each("Author") { |a| a.text }.join(", ") \+ " (著)" desc += "<br>発売日:" \+ itmat.elements\["PublicationDate"\].text.gsub(/-/, '/') desc += "<br>" \+ itmat.elements\["ListPrice/FormattedPrice"\].text entry.description = desc entry.date = Time.now end end print "Content-Type:application/rss+xml\\r\\n\\r\\n" print rss #open("oreilly-bestseller.xml", "w") { |out| \# out.print rss #} #``` ※IE7だと application/rss だけではフィードだと認識されなかった。

2008年1月3日 · Toshimitsu Takahashi