1#-- 2# httpstatus.rb -- HTTPStatus Class 3# 4# Author: IPR -- Internet Programming with Ruby -- writers 5# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou 6# Copyright (c) 2002 Internet Programming with Ruby writers. All rights 7# reserved. 8# 9# $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $ 10 11module WEBrick 12 13 ## 14 # This module is used to manager HTTP status codes. 15 # 16 # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for more 17 # information. 18 module HTTPStatus 19 20 ## 21 # Root of the HTTP status class hierarchy 22 class Status < StandardError 23 def initialize(*args) # :nodoc: 24 args[0] = AccessLog.escape(args[0]) unless args.empty? 25 super(*args) 26 end 27 class << self 28 attr_reader :code, :reason_phrase # :nodoc: 29 end 30 31 # Returns the HTTP status code 32 def code() self::class::code end 33 34 # Returns the HTTP status description 35 def reason_phrase() self::class::reason_phrase end 36 37 alias to_i code # :nodoc: 38 end 39 40 # Root of the HTTP info statuses 41 class Info < Status; end 42 # Root of the HTTP sucess statuses 43 class Success < Status; end 44 # Root of the HTTP redirect statuses 45 class Redirect < Status; end 46 # Root of the HTTP error statuses 47 class Error < Status; end 48 # Root of the HTTP client error statuses 49 class ClientError < Error; end 50 # Root of the HTTP server error statuses 51 class ServerError < Error; end 52 53 class EOFError < StandardError; end 54 55 # HTTP status codes and descriptions 56 StatusMessage = { # :nodoc: 57 100 => 'Continue', 58 101 => 'Switching Protocols', 59 200 => 'OK', 60 201 => 'Created', 61 202 => 'Accepted', 62 203 => 'Non-Authoritative Information', 63 204 => 'No Content', 64 205 => 'Reset Content', 65 206 => 'Partial Content', 66 207 => 'Multi-Status', 67 300 => 'Multiple Choices', 68 301 => 'Moved Permanently', 69 302 => 'Found', 70 303 => 'See Other', 71 304 => 'Not Modified', 72 305 => 'Use Proxy', 73 307 => 'Temporary Redirect', 74 400 => 'Bad Request', 75 401 => 'Unauthorized', 76 402 => 'Payment Required', 77 403 => 'Forbidden', 78 404 => 'Not Found', 79 405 => 'Method Not Allowed', 80 406 => 'Not Acceptable', 81 407 => 'Proxy Authentication Required', 82 408 => 'Request Timeout', 83 409 => 'Conflict', 84 410 => 'Gone', 85 411 => 'Length Required', 86 412 => 'Precondition Failed', 87 413 => 'Request Entity Too Large', 88 414 => 'Request-URI Too Large', 89 415 => 'Unsupported Media Type', 90 416 => 'Request Range Not Satisfiable', 91 417 => 'Expectation Failed', 92 422 => 'Unprocessable Entity', 93 423 => 'Locked', 94 424 => 'Failed Dependency', 95 426 => 'Upgrade Required', 96 428 => 'Precondition Required', 97 429 => 'Too Many Requests', 98 431 => 'Request Header Fields Too Large', 99 500 => 'Internal Server Error', 100 501 => 'Not Implemented', 101 502 => 'Bad Gateway', 102 503 => 'Service Unavailable', 103 504 => 'Gateway Timeout', 104 505 => 'HTTP Version Not Supported', 105 507 => 'Insufficient Storage', 106 511 => 'Network Authentication Required', 107 } 108 109 # Maps a status code to the corresponding Status class 110 CodeToError = {} # :nodoc: 111 112 # Creates a status or error class for each status code and 113 # populates the CodeToError map. 114 StatusMessage.each{|code, message| 115 message.freeze 116 var_name = message.gsub(/[ \-]/,'_').upcase 117 err_name = message.gsub(/[ \-]/,'') 118 119 case code 120 when 100...200; parent = Info 121 when 200...300; parent = Success 122 when 300...400; parent = Redirect 123 when 400...500; parent = ClientError 124 when 500...600; parent = ServerError 125 end 126 127 const_set("RC_#{var_name}", code) 128 err_class = Class.new(parent) 129 err_class.instance_variable_set(:@code, code) 130 err_class.instance_variable_set(:@reason_phrase, message) 131 const_set(err_name, err_class) 132 CodeToError[code] = err_class 133 } 134 135 ## 136 # Returns the description corresponding to the HTTP status +code+ 137 # 138 # WEBrick::HTTPStatus.reason_phrase 404 139 # => "Not Found" 140 def reason_phrase(code) 141 StatusMessage[code.to_i] 142 end 143 144 ## 145 # Is +code+ an informational status? 146 def info?(code) 147 code.to_i >= 100 and code.to_i < 200 148 end 149 150 ## 151 # Is +code+ a successful status? 152 def success?(code) 153 code.to_i >= 200 and code.to_i < 300 154 end 155 156 ## 157 # Is +code+ a redirection status? 158 def redirect?(code) 159 code.to_i >= 300 and code.to_i < 400 160 end 161 162 ## 163 # Is +code+ an error status? 164 def error?(code) 165 code.to_i >= 400 and code.to_i < 600 166 end 167 168 ## 169 # Is +code+ a client error status? 170 def client_error?(code) 171 code.to_i >= 400 and code.to_i < 500 172 end 173 174 ## 175 # Is +code+ a server error status? 176 def server_error?(code) 177 code.to_i >= 500 and code.to_i < 600 178 end 179 180 ## 181 # Returns the status class corresponding to +code+ 182 # 183 # WEBrick::HTTPStatus[302] 184 # => WEBrick::HTTPStatus::NotFound 185 # 186 def self.[](code) 187 CodeToError[code] 188 end 189 190 module_function :reason_phrase 191 module_function :info?, :success?, :redirect?, :error? 192 module_function :client_error?, :server_error? 193 end 194end 195