rubysl-webrick 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rubysl/webrick.rb +2 -0
  9. data/lib/rubysl/webrick/version.rb +5 -0
  10. data/lib/rubysl/webrick/webrick.rb +29 -0
  11. data/lib/webrick.rb +1 -0
  12. data/lib/webrick/accesslog.rb +67 -0
  13. data/lib/webrick/cgi.rb +257 -0
  14. data/lib/webrick/compat.rb +15 -0
  15. data/lib/webrick/config.rb +97 -0
  16. data/lib/webrick/cookie.rb +110 -0
  17. data/lib/webrick/htmlutils.rb +25 -0
  18. data/lib/webrick/httpauth.rb +45 -0
  19. data/lib/webrick/httpauth/authenticator.rb +79 -0
  20. data/lib/webrick/httpauth/basicauth.rb +65 -0
  21. data/lib/webrick/httpauth/digestauth.rb +343 -0
  22. data/lib/webrick/httpauth/htdigest.rb +91 -0
  23. data/lib/webrick/httpauth/htgroup.rb +61 -0
  24. data/lib/webrick/httpauth/htpasswd.rb +83 -0
  25. data/lib/webrick/httpauth/userdb.rb +29 -0
  26. data/lib/webrick/httpproxy.rb +254 -0
  27. data/lib/webrick/httprequest.rb +365 -0
  28. data/lib/webrick/httpresponse.rb +327 -0
  29. data/lib/webrick/https.rb +63 -0
  30. data/lib/webrick/httpserver.rb +210 -0
  31. data/lib/webrick/httpservlet.rb +22 -0
  32. data/lib/webrick/httpservlet/abstract.rb +71 -0
  33. data/lib/webrick/httpservlet/cgi_runner.rb +45 -0
  34. data/lib/webrick/httpservlet/cgihandler.rb +104 -0
  35. data/lib/webrick/httpservlet/erbhandler.rb +54 -0
  36. data/lib/webrick/httpservlet/filehandler.rb +398 -0
  37. data/lib/webrick/httpservlet/prochandler.rb +33 -0
  38. data/lib/webrick/httpstatus.rb +126 -0
  39. data/lib/webrick/httputils.rb +391 -0
  40. data/lib/webrick/httpversion.rb +49 -0
  41. data/lib/webrick/log.rb +88 -0
  42. data/lib/webrick/server.rb +200 -0
  43. data/lib/webrick/ssl.rb +126 -0
  44. data/lib/webrick/utils.rb +100 -0
  45. data/lib/webrick/version.rb +13 -0
  46. data/rubysl-webrick.gemspec +23 -0
  47. metadata +145 -0
@@ -0,0 +1,63 @@
1
+ #
2
+ # https.rb -- SSL/TLS enhancement for HTTPServer
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2001 GOTOU Yuuzou
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: https.rb,v 1.15 2003/07/22 19:20:42 gotoyuzo Exp $
10
+
11
+ require 'webrick/ssl'
12
+
13
+ module WEBrick
14
+ module Config
15
+ HTTP.update(SSL)
16
+ end
17
+
18
+ class HTTPRequest
19
+ attr_reader :cipher, :server_cert, :client_cert
20
+
21
+ alias orig_parse parse
22
+
23
+ def parse(socket=nil)
24
+ if socket.respond_to?(:cert)
25
+ @server_cert = socket.cert || @config[:SSLCertificate]
26
+ @client_cert = socket.peer_cert
27
+ @client_cert_chain = socket.peer_cert_chain
28
+ @cipher = socket.cipher
29
+ end
30
+ orig_parse(socket)
31
+ end
32
+
33
+ alias orig_parse_uri parse_uri
34
+
35
+ def parse_uri(str, scheme="https")
36
+ if @server_cert
37
+ return orig_parse_uri(str, scheme)
38
+ end
39
+ return orig_parse_uri(str)
40
+ end
41
+
42
+ alias orig_meta_vars meta_vars
43
+
44
+ def meta_vars
45
+ meta = orig_meta_vars
46
+ if @server_cert
47
+ meta["HTTPS"] = "on"
48
+ meta["SSL_SERVER_CERT"] = @server_cert.to_pem
49
+ meta["SSL_CLIENT_CERT"] = @client_cert ? @client_cert.to_pem : ""
50
+ if @client_cert_chain
51
+ @client_cert_chain.each_with_index{|cert, i|
52
+ meta["SSL_CLIENT_CERT_CHAIN_#{i}"] = cert.to_pem
53
+ }
54
+ end
55
+ meta["SSL_CIPHER"] = @cipher[0]
56
+ meta["SSL_PROTOCOL"] = @cipher[1]
57
+ meta["SSL_CIPHER_USEKEYSIZE"] = @cipher[2].to_s
58
+ meta["SSL_CIPHER_ALGKEYSIZE"] = @cipher[3].to_s
59
+ end
60
+ meta
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,210 @@
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
+
11
+ require 'webrick/server'
12
+ require 'webrick/httputils'
13
+ require 'webrick/httpstatus'
14
+ require 'webrick/httprequest'
15
+ require 'webrick/httpresponse'
16
+ require 'webrick/httpservlet'
17
+ require 'webrick/accesslog'
18
+
19
+ module 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
210
+ end
@@ -0,0 +1,22 @@
1
+ #
2
+ # httpservlet.rb -- HTTPServlet Utility File
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: httpservlet.rb,v 1.21 2003/02/23 12:24:46 gotoyuzo Exp $
10
+
11
+ require 'webrick/httpservlet/abstract'
12
+ require 'webrick/httpservlet/filehandler'
13
+ require 'webrick/httpservlet/cgihandler'
14
+ require 'webrick/httpservlet/erbhandler'
15
+ require 'webrick/httpservlet/prochandler'
16
+
17
+ module WEBrick
18
+ module HTTPServlet
19
+ FileHandler.add_handler("cgi", CGIHandler)
20
+ FileHandler.add_handler("rhtml", ERBHandler)
21
+ end
22
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # httpservlet.rb -- HTTPServlet Module
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU Yuuzou
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $
10
+
11
+ require 'thread'
12
+
13
+ require 'webrick/htmlutils'
14
+ require 'webrick/httputils'
15
+ require 'webrick/httpstatus'
16
+
17
+ module WEBrick
18
+ module HTTPServlet
19
+ class HTTPServletError < StandardError; end
20
+
21
+ class AbstractServlet
22
+ def self.get_instance(config, *options)
23
+ self.new(config, *options)
24
+ end
25
+
26
+ def initialize(server, *options)
27
+ @server = @config = server
28
+ @logger = @server[:Logger]
29
+ @options = options
30
+ end
31
+
32
+ def service(req, res)
33
+ method_name = "do_" + req.request_method.gsub(/-/, "_")
34
+ if respond_to?(method_name)
35
+ __send__(method_name, req, res)
36
+ else
37
+ raise HTTPStatus::MethodNotAllowed,
38
+ "unsupported method `#{req.request_method}'."
39
+ end
40
+ end
41
+
42
+ def do_GET(req, res)
43
+ raise HTTPStatus::NotFound, "not found."
44
+ end
45
+
46
+ def do_HEAD(req, res)
47
+ do_GET(req, res)
48
+ end
49
+
50
+ def do_OPTIONS(req, res)
51
+ m = self.methods.grep(/^do_[A-Z]+$/)
52
+ m.collect!{|i| i.sub(/do_/, "") }
53
+ m.sort!
54
+ res["allow"] = m.join(",")
55
+ end
56
+
57
+ private
58
+
59
+ def redirect_to_directory_uri(req, res)
60
+ if req.path[-1] != ?/
61
+ location = req.path + "/"
62
+ if req.query_string && req.query_string.size > 0
63
+ location << "?" << req.query_string
64
+ end
65
+ res.set_redirect(HTTPStatus::MovedPermanently, location)
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,45 @@
1
+ #
2
+ # cgi_runner.rb -- CGI launcher.
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $
10
+
11
+ def sysread(io, size)
12
+ buf = ""
13
+ while size > 0
14
+ tmp = io.sysread(size)
15
+ buf << tmp
16
+ size -= tmp.size
17
+ end
18
+ return buf
19
+ end
20
+
21
+ STDIN.binmode
22
+
23
+ buf = ""
24
+ len = sysread(STDIN, 8).to_i
25
+ out = sysread(STDIN, len)
26
+ STDOUT.reopen(open(out, "w"))
27
+
28
+ len = sysread(STDIN, 8).to_i
29
+ err = sysread(STDIN, len)
30
+ STDERR.reopen(open(err, "w"))
31
+
32
+ len = sysread(STDIN, 8).to_i
33
+ dump = sysread(STDIN, len)
34
+ hash = Marshal.restore(dump)
35
+ ENV.keys.each{|name| ENV.delete(name) }
36
+ hash.each{|k, v| ENV[k] = v if v }
37
+
38
+ dir = File::dirname(ENV["SCRIPT_FILENAME"])
39
+ Dir::chdir dir
40
+
41
+ if interpreter = ARGV[0]
42
+ exec(interpreter, ENV["SCRIPT_FILENAME"])
43
+ # NOTREACHED
44
+ end
45
+ exec ENV["SCRIPT_FILENAME"]
@@ -0,0 +1,104 @@
1
+ #
2
+ # cgihandler.rb -- CGIHandler Class
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $
10
+
11
+ require 'rbconfig'
12
+ require 'tempfile'
13
+ require 'webrick/config'
14
+ require 'webrick/httpservlet/abstract'
15
+
16
+ module WEBrick
17
+ module HTTPServlet
18
+
19
+ class CGIHandler < AbstractServlet
20
+ Ruby = File::join(::Config::CONFIG['bindir'],
21
+ ::Config::CONFIG['ruby_install_name'])
22
+ Ruby << ::Config::CONFIG['EXEEXT']
23
+ CGIRunner = "\"#{Ruby}\" \"#{Config::LIBDIR}/httpservlet/cgi_runner.rb\""
24
+
25
+ def initialize(server, name)
26
+ super
27
+ @script_filename = name
28
+ @tempdir = server[:TempDir]
29
+ @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
30
+ end
31
+
32
+ def do_GET(req, res)
33
+ data = nil
34
+ status = -1
35
+
36
+ cgi_in = IO::popen(@cgicmd, "wb")
37
+ cgi_out = Tempfile.new("webrick.cgiout.", @tempdir)
38
+ cgi_err = Tempfile.new("webrick.cgierr.", @tempdir)
39
+ begin
40
+ cgi_in.sync = true
41
+ meta = req.meta_vars
42
+ meta["SCRIPT_FILENAME"] = @script_filename
43
+ meta["PATH"] = @config[:CGIPathEnv]
44
+ if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
45
+ meta["SystemRoot"] = ENV["SystemRoot"]
46
+ end
47
+ dump = Marshal.dump(meta)
48
+
49
+ cgi_in.write("%8d" % cgi_out.path.size)
50
+ cgi_in.write(cgi_out.path)
51
+ cgi_in.write("%8d" % cgi_err.path.size)
52
+ cgi_in.write(cgi_err.path)
53
+ cgi_in.write("%8d" % dump.size)
54
+ cgi_in.write(dump)
55
+
56
+ if req.body and req.body.size > 0
57
+ cgi_in.write(req.body)
58
+ end
59
+ ensure
60
+ cgi_in.close
61
+ status = $?.exitstatus
62
+ sleep 0.1 if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
63
+ data = cgi_out.read
64
+ cgi_out.close(true)
65
+ if errmsg = cgi_err.read
66
+ if errmsg.size > 0
67
+ @logger.error("CGIHandler: #{@script_filename}:\n" + errmsg)
68
+ end
69
+ end
70
+ cgi_err.close(true)
71
+ end
72
+
73
+ if status != 0
74
+ @logger.error("CGIHandler: #{@script_filename} exit with #{status}")
75
+ end
76
+
77
+ data = "" unless data
78
+ raw_header, body = data.split(/^[\xd\xa]+/on, 2)
79
+ raise HTTPStatus::InternalServerError,
80
+ "Premature end of script headers: #{@script_filename}" if body.nil?
81
+
82
+ begin
83
+ header = HTTPUtils::parse_header(raw_header)
84
+ if /^(\d+)/ =~ header['status'][0]
85
+ res.status = $1.to_i
86
+ header.delete('status')
87
+ end
88
+ if header.has_key?('set-cookie')
89
+ header['set-cookie'].each{|k|
90
+ res.cookies << Cookie.parse_set_cookie(k)
91
+ }
92
+ header.delete('set-cookie')
93
+ end
94
+ header.each{|key, val| res[key] = val.join(", ") }
95
+ rescue => ex
96
+ raise HTTPStatus::InternalServerError, ex.message
97
+ end
98
+ res.body = body
99
+ end
100
+ alias do_POST do_GET
101
+ end
102
+
103
+ end
104
+ end