Class: Alone
- Inherits:
-
Object
- Object
- Alone
- Defined in:
- lib/al_main.rb
Overview
Aloneメインクラス
Aloneのベースとなる機能を、まとめている。
Defined Under Namespace
Classes: OutputTrap
Constant Summary collapse
- CHAR_ENT_REF =
escape_html用定数テーブル
{'<'=>'<', '>'=>'>', '&'=>'&', '"'=>'"', '\''=>''', "\r\n"=>'<br>', "\r"=>'<br>', "\n"=>'<br>' }
- @@headers =
Returns httpヘッダ.
[ "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" ]
nil
- @@flag_redirect =
Returns リダイレクトするかのフラグ.
false
- @@flag_send_http_headers =
Returns httpヘッダを送ったかのフラグ.
false
- @@ctrl =
Returns コントローラ名.
""
- @@action =
Returns アクション名.
""
- @@log =
Returns ロガーオブジェクト.
nil
Class Method Summary collapse
-
._start ⇒ Object
初期化.
-
.action ⇒ String
Getter アクション名.
-
.add_http_header(header) ⇒ Object
httpヘッダの追加.
-
.ctrl ⇒ String
Getter コントローラ名.
-
.decode_uri_component(s) ⇒ String
URIデコード.
-
.delete_cookie(name, path = nil) ⇒ Object
クッキーの消去.
-
.delete_http_header(header) ⇒ Object
httpヘッダの削除.
-
.encode_uri_component(s) ⇒ String
URIエンコード.
-
.escape_backslash(s) ⇒ String
クォート文字をバックスラッシュでエスケープする.
-
.escape_html(s) ⇒ String
html特殊文字のエスケープ.
-
.escape_html_br(s) ⇒ String
html特殊文字のエスケープ with 改行文字.
-
.get_cookie(name) ⇒ String, NilClass
クッキーの取得.
-
.handle_error(ex) ⇒ Object
エラーハンドラ.
-
.handle_error_display(ex) ⇒ Object
エラーハンドラ:エラー詳細表示.
-
.handle_error_static_page(ex) ⇒ Object
エラーハンドラ:静的ページを表示.
-
.log(*args) ⇒ Logger
ログ出力.
-
.main ⇒ Object
メイン.
-
.make_uri(arg = {}) ⇒ String
リンク用のURIを生成する.
-
.redirect_to(uri) ⇒ Object
リダイレクト設定.
-
.request_uri ⇒ String
リクエストされたURIを返す.
-
.send_http_headers ⇒ Object
httpヘッダの送信.
-
.set_cookie(name, value, expire = nil, path = nil, other = nil) ⇒ Object
クッキーの設定.
Class Method Details
._start ⇒ Object
初期化
476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/al_main.rb', line 476 def self._start() if ENV.has_key?("GATEWAY_INTERFACE") query_string = ENV["QUERY_STRING"] || "" /(^|&)ctrl=([a-zA-Z0-9_\-\/]*)/ =~ query_string @@ctrl = $2.to_s.dup /(^|&)action=([a-zA-Z0-9_\-\/]*)/ =~ query_string @@action = $2.to_s.dup $stdout = OutputTrap.new $stderr = $stdout end Encoding.default_external = AL_CHARSET end |
.action ⇒ String
Getter アクション名
57 58 59 |
# File 'lib/al_main.rb', line 57 def self.action() return @@action end |
.add_http_header(header) ⇒ Object
httpヘッダの追加
実際にhttpヘッダが送られる前に、使用する必要がある。 httpヘッダは、send_http_headers() メソッドで送られる。 典型的には、最初にユーザコードで文字列などが表示される直前に、 ヘッダが出力されるので、それまでに使用する。
173 174 175 |
# File 'lib/al_main.rb', line 173 def self.add_http_header( header ) @@headers << header.chomp.gsub( /\r?\n[^ \t]|\r[^\n \t]/, ' ' ) end |
.ctrl ⇒ String
Getter コントローラ名
48 49 50 |
# File 'lib/al_main.rb', line 48 def self.ctrl() return @@ctrl end |
.decode_uri_component(s) ⇒ String
URIデコード
314 315 316 317 318 319 |
# File 'lib/al_main.rb', line 314 def self.decode_uri_component( s ) a = s.to_s.dup.force_encoding( Encoding::ASCII_8BIT ) a.gsub!( /%([0-9a-fA-F]{2})/ ) { $1.hex.chr } a.force_encoding( AL_CHARSET ) # TODO: UTF-8(あるいはその他の漢字コード)として無効なコードが来たらどうする? end |
.delete_cookie(name, path = nil) ⇒ Object
クッキーの消去
httpヘッダに出力する関係上、ヘッダ出力前にコールする必要がある。
267 268 269 270 271 272 273 274 275 |
# File 'lib/al_main.rb', line 267 def self.( name, path = nil ) # 既にヘッダへ出力予約されているものがあれば削除 target = "Set-Cookie: #{name}=" @@headers.delete_if { |h| h.start_with?( target ) } = "Set-Cookie: #{name}=; expires=Thu, 08-Jun-1944 00:00:00 GMT" << "; path=#{path}" if path @@headers << end |
.delete_http_header(header) ⇒ Object
httpヘッダの削除
実際にhttpヘッダが送られる前に、使用する必要がある。 デフォルトで送信されるヘッダ Cache-Control: を止めることができる。
187 188 189 |
# File 'lib/al_main.rb', line 187 def self.delete_http_header( header ) @@headers.delete_if { |a| a.start_with?( header ) } end |
.encode_uri_component(s) ⇒ String
URIエンコード
301 302 303 304 305 |
# File 'lib/al_main.rb', line 301 def self.encode_uri_component( s ) a = s.to_s.dup a.force_encoding( Encoding::ASCII_8BIT ) a.gsub( /[^a-zA-Z0-9!'\(\)*\-._~]/ ) { |c| "%#{c.unpack('H2')[0]}" } end |
.escape_backslash(s) ⇒ String
クォート文字をバックスラッシュでエスケープする
対象は、シングルクォート、ダブルクォート、バックスラッシュ、NULL
405 406 407 |
# File 'lib/al_main.rb', line 405 def self.escape_backslash( s ) s.to_s.gsub( /['"\\\x0]/ ) { |q| "\\#{q}" } end |
.escape_html(s) ⇒ String
html特殊文字のエスケープ
379 380 381 |
# File 'lib/al_main.rb', line 379 def self.escape_html( s ) return s.to_s.gsub( /[<>&"']/, CHAR_ENT_REF ) end |
.escape_html_br(s) ⇒ String
html特殊文字のエスケープ with 改行文字
html特殊文字のエスケープに加え、改行文字を
タグへ変更する。
392 393 394 |
# File 'lib/al_main.rb', line 392 def self.escape_html_br( s ) return s.to_s.gsub( /([<>&"']|\r\n|\r|\n)/, CHAR_ENT_REF ) end |
.get_cookie(name) ⇒ String, NilClass
クッキーの取得
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/al_main.rb', line 221 def self.( name ) if ! @@cookies @@cookies = {} = ENV['HTTP_COOKIE'] return nil if ! = .split( ';' ) .each do |c| (k,v) = c.split( '=', 2 ) next if ! v @@cookies[k.strip.to_sym] = decode_uri_component( v ) end end return @@cookies[name.to_sym] end |
.handle_error(ex) ⇒ Object
エラーハンドラ
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/al_main.rb', line 89 def self.handle_error( ex ) if ex.class == SystemExit send_http_headers() else __send__( AL_ERROR_HANDLER, ex ) log( ex ) end exit end |
.handle_error_display(ex) ⇒ Object
エラーハンドラ:エラー詳細表示
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/al_main.rb', line 134 def self.handle_error_display( ex ) add_http_header( "Status: 500 Internal Server Error" ) send_http_headers() puts AL_TEMPLATE_HEADER puts AL_TEMPLATE_BODY puts '<h1 class="al-error-display">Alone: Error detected.</h1>' puts "<h2 class=\"al-error-display\">#{ex.class} occurred.</h2>" puts '<pre class="al-error-display">' puts ' ' + escape_html( ex. ) puts '</pre>' puts '<h2 class="al-error-display">Backtrace</h2>' puts '<pre class="al-error-display">' ex.backtrace.each do |bt| puts ' ' + escape_html( bt ) end puts '</pre>' puts '<h2 class="al-error-display">Environment</h2>' puts '<pre class="al-error-display">' ENV.each {|k,v| puts " #{k} = #{escape_html(v)}" } puts '</pre>' puts AL_TEMPLATE_FOOTER end |
.handle_error_static_page(ex) ⇒ Object
エラーハンドラ:静的ページを表示
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/al_main.rb', line 104 def self.handle_error_static_page( ex ) status_code = nil = nil # check status code in @@headers. @@headers.each do |h| if /^Status: (\d+)(.*)$/ =~ h status_code = $1 = $1 + $2 end end if ! status_code status_code = "500" # default 500 Internal Server Error = "Internal Server Error" Alone::add_http_header( "Status: 500 Internal Server Error" ) end # display error page. send_http_headers() begin print File.read( "#{AL_BASEDIR}/templates/#{status_code}.html" ) rescue print end end |
.log(*args) ⇒ Logger
ログ出力
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/al_main.rb', line 418 def self.log( *args ) return nil if ! defined? AL_LOG_DEV require "logger" if !@@log @@log = Logger.new( AL_LOG_DEV, AL_LOG_AGE, AL_LOG_SIZE ) @@log.level = Logger::INFO end return @@log if args.empty? msg,severity,progname = *args s = { :fatal=>Logger::FATAL, :error=>Logger::ERROR, :warn=>Logger::WARN, :info=>Logger::INFO, :debug=>Logger::DEBUG }[ severity ] case msg when String @@log.add(s || Logger::INFO, msg, progname) when Exception @@log.add(s || Logger::ERROR, "#{msg.class} / #{msg.}", progname) @@log.add(s || Logger::ERROR, "BACKTRACE: \n " + msg.backtrace.join("\n ") + "\n", progname) else @@log.add(s || Logger::INFO, msg.inspect, progname) end return @@log end |
.main ⇒ Object
メイン
ユーザコードがブロックで渡されるので、それを実行する。 例外はすべてキャッチして、正当なhtmlで表示する。
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/al_main.rb', line 69 def self.main() # リダイレクトするなら、ヘッダ出力のみで終了(htmlコンテンツは必要ない) if @@flag_redirect send_http_headers() exit end begin yield() send_http_headers() rescue Exception => ex handle_error( ex ) end end |
.make_uri(arg = {}) ⇒ String
リンク用のURIを生成する
このメソッドは、escape_html()した値を返さない。 生成した値は、アトリビュート値にもテンプレートにも使われる。 少々危険な気もするが、エスケープはテンプレートエンジンの仕事にしなければ アプリケーションが破綻する。
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/al_main.rb', line 354 def self.make_uri( arg = {} ) uri = "#{ENV['SCRIPT_NAME']}?ctrl=#{arg[:ctrl] || @@ctrl}" uri << "&action=#{arg[:action]}" if arg[:action] arg.each do |k,v| next if k == :ctrl || k == :action if v.class == Array v.each do |v1| uri << "&#{k}=#{encode_uri_component(v1)}" end else uri << "&#{k}=#{encode_uri_component(v)}" end end return uri end |
.redirect_to(uri) ⇒ Object
リダイレクト設定
283 284 285 286 287 288 289 290 291 292 |
# File 'lib/al_main.rb', line 283 def self.redirect_to( uri ) if @@flag_send_http_headers raise "HTTP header was already sent." end raise "Invalid URI" if /[\r\n]/ =~ uri @@headers << "Location: #{uri}" @@headers << "Status: 302 Found" @@flag_redirect = true end |
.request_uri ⇒ String
リクエストされたURIを返す
327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/al_main.rb', line 327 def self.request_uri() if ENV['REQUEST_URI'] return ENV['REQUEST_URI'] end if ENV['QUERY_STRING'] return "#{ENV['SCRIPT_NAME']}?#{ENV['QUERY_STRING']}" end return ENV['SCRIPT_NAME'] end |
.send_http_headers ⇒ Object
httpヘッダの送信
送信済みなら何もしないので、何度よんでも問題ない。
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/al_main.rb', line 198 def self.send_http_headers() return if @@flag_send_http_headers @@flag_send_http_headers = true flag_content_type = false @@headers.each do |h| puts h flag_content_type = true if h.start_with?( "Content-Type:" ) end if ! flag_content_type print "Content-Type: text/html; charset=#{AL_CHARSET}\n" end print "\n" end |
.set_cookie(name, value, expire = nil, path = nil, other = nil) ⇒ Object
クッキーの設定
httpヘッダに出力する関係上、ヘッダ出力前にコールする必要がある。
250 251 252 253 254 255 256 |
# File 'lib/al_main.rb', line 250 def self.( name, value, expire = nil, path = nil, other = nil ) = "Set-Cookie: #{name}=#{encode_uri_component( value )}" << "; expires=#{expire.to_s}" if expire << "; path=#{path}" if path << "; #{other}" if other @@headers << end |