source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpserver.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 5.6 KB
Line 
1#
2# httpserver.rb -- HTTPServer 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: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $
10
11require 'webrick/server'
12require 'webrick/httputils'
13require 'webrick/httpstatus'
14require 'webrick/httprequest'
15require 'webrick/httpresponse'
16require 'webrick/httpservlet'
17require 'webrick/accesslog'
18
19module WEBrick
20 class HTTPServerError < ServerError; end
21
22 class HTTPServer < ::WEBrick::GenericServer
23 def initialize(config={}, default=Config::HTTP)
24 super
25 @http_version = HTTPVersion::convert(@config[:HTTPVersion])
26
27 @mount_tab = MountTable.new
28 if @config[:DocumentRoot]
29 mount("/", HTTPServlet::FileHandler, @config[:DocumentRoot],
30 @config[:DocumentRootOptions])
31 end
32
33 unless @config[:AccessLog]
34 @config[:AccessLog] = [
35 [ $stderr, AccessLog::COMMON_LOG_FORMAT ],
36 [ $stderr, AccessLog::REFERER_LOG_FORMAT ]
37 ]
38 end
39
40 @virtual_hosts = Array.new
41 end
42
43 def run(sock)
44 while true
45 res = HTTPResponse.new(@config)
46 req = HTTPRequest.new(@config)
47 server = self
48 begin
49 timeout = @config[:RequestTimeout]
50 while timeout > 0
51 break if IO.select([sock], nil, nil, 0.5)
52 timeout = 0 if @status != :Running
53 timeout -= 0.5
54 end
55 raise HTTPStatus::EOFError if timeout <= 0 || sock.eof?
56 req.parse(sock)
57 res.request_method = req.request_method
58 res.request_uri = req.request_uri
59 res.request_http_version = req.http_version
60 res.keep_alive = req.keep_alive?
61 server = lookup_server(req) || self
62 if callback = server[:RequestCallback] || server[:RequestHandler]
63 callback.call(req, res)
64 end
65 server.service(req, res)
66 rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
67 res.set_error(ex)
68 rescue HTTPStatus::Error => ex
69 @logger.error(ex.message)
70 res.set_error(ex)
71 rescue HTTPStatus::Status => ex
72 res.status = ex.code
73 rescue StandardError => ex
74 @logger.error(ex)
75 res.set_error(ex, true)
76 ensure
77 if req.request_line
78 req.fixup()
79 res.send_response(sock)
80 server.access_log(@config, req, res)
81 end
82 end
83 break if @http_version < "1.1"
84 break unless req.keep_alive?
85 break unless res.keep_alive?
86 end
87 end
88
89 def service(req, res)
90 if req.unparsed_uri == "*"
91 if req.request_method == "OPTIONS"
92 do_OPTIONS(req, res)
93 raise HTTPStatus::OK
94 end
95 raise HTTPStatus::NotFound, "`#{req.unparsed_uri}' not found."
96 end
97
98 servlet, options, script_name, path_info = search_servlet(req.path)
99 raise HTTPStatus::NotFound, "`#{req.path}' not found." unless servlet
100 req.script_name = script_name
101 req.path_info = path_info
102 si = servlet.get_instance(self, *options)
103 @logger.debug(format("%s is invoked.", si.class.name))
104 si.service(req, res)
105 end
106
107 def do_OPTIONS(req, res)
108 res["allow"] = "GET,HEAD,POST,OPTIONS"
109 end
110
111 def mount(dir, servlet, *options)
112 @logger.debug(sprintf("%s is mounted on %s.", servlet.inspect, dir))
113 @mount_tab[dir] = [ servlet, options ]
114 end
115
116 def mount_proc(dir, proc=nil, &block)
117 proc ||= block
118 raise HTTPServerError, "must pass a proc or block" unless proc
119 mount(dir, HTTPServlet::ProcHandler.new(proc))
120 end
121
122 def unmount(dir)
123 @logger.debug(sprintf("unmount %s.", dir))
124 @mount_tab.delete(dir)
125 end
126 alias umount unmount
127
128 def search_servlet(path)
129 script_name, path_info = @mount_tab.scan(path)
130 servlet, options = @mount_tab[script_name]
131 if servlet
132 [ servlet, options, script_name, path_info ]
133 end
134 end
135
136 def virtual_host(server)
137 @virtual_hosts << server
138 @virtual_hosts = @virtual_hosts.sort_by{|s|
139 num = 0
140 num -= 4 if s[:BindAddress]
141 num -= 2 if s[:Port]
142 num -= 1 if s[:ServerName]
143 num
144 }
145 end
146
147 def lookup_server(req)
148 @virtual_hosts.find{|s|
149 (s[:BindAddress].nil? || req.addr[3] == s[:BindAddress]) &&
150 (s[:Port].nil? || req.port == s[:Port]) &&
151 ((s[:ServerName].nil? || req.host == s[:ServerName]) ||
152 (!s[:ServerAlias].nil? && s[:ServerAlias].find{|h| h === req.host}))
153 }
154 end
155
156 def access_log(config, req, res)
157 param = AccessLog::setup_params(config, req, res)
158 @config[:AccessLog].each{|logger, fmt|
159 logger << AccessLog::format(fmt+"\n", param)
160 }
161 end
162
163 class MountTable
164 def initialize
165 @tab = Hash.new
166 compile
167 end
168
169 def [](dir)
170 dir = normalize(dir)
171 @tab[dir]
172 end
173
174 def []=(dir, val)
175 dir = normalize(dir)
176 @tab[dir] = val
177 compile
178 val
179 end
180
181 def delete(dir)
182 dir = normalize(dir)
183 res = @tab.delete(dir)
184 compile
185 res
186 end
187
188 def scan(path)
189 @scanner =~ path
190 [ $&, $' ]
191 end
192
193 private
194
195 def compile
196 k = @tab.keys
197 k.sort!
198 k.reverse!
199 k.collect!{|path| Regexp.escape(path) }
200 @scanner = Regexp.new("^(" + k.join("|") +")(?=/|$)")
201 end
202
203 def normalize(dir)
204 ret = dir ? dir.dup : ""
205 ret.sub!(%r|/+$|, "")
206 ret
207 end
208 end
209 end
210end
Note: See TracBrowser for help on using the repository browser.