diff options
Diffstat (limited to 'lib/webrick/httpservlet')
| -rw-r--r-- | lib/webrick/httpservlet/abstract.rb | 101 | ||||
| -rw-r--r-- | lib/webrick/httpservlet/cgi_runner.rb | 10 | ||||
| -rw-r--r-- | lib/webrick/httpservlet/cgihandler.rb | 74 | ||||
| -rw-r--r-- | lib/webrick/httpservlet/erbhandler.rb | 54 | ||||
| -rw-r--r-- | lib/webrick/httpservlet/filehandler.rb | 224 | ||||
| -rw-r--r-- | lib/webrick/httpservlet/prochandler.rb | 24 |
6 files changed, 372 insertions, 115 deletions
diff --git a/lib/webrick/httpservlet/abstract.rb b/lib/webrick/httpservlet/abstract.rb index 5375c4622d..bccb091861 100644 --- a/lib/webrick/httpservlet/abstract.rb +++ b/lib/webrick/httpservlet/abstract.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false # # httpservlet.rb -- HTTPServlet Module # @@ -8,27 +9,96 @@ # # $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $ -require 'thread' - -require 'webrick/htmlutils' -require 'webrick/httputils' -require 'webrick/httpstatus' +require_relative '../htmlutils' +require_relative '../httputils' +require_relative '../httpstatus' module WEBrick module HTTPServlet class HTTPServletError < StandardError; end + ## + # AbstractServlet allows HTTP server modules to be reused across multiple + # servers and allows encapsulation of functionality. + # + # By default a servlet will respond to GET, HEAD (through an alias to GET) + # and OPTIONS requests. + # + # By default a new servlet is initialized for every request. A servlet + # instance can be reused by overriding ::get_instance in the + # AbstractServlet subclass. + # + # == A Simple Servlet + # + # class Simple < WEBrick::HTTPServlet::AbstractServlet + # def do_GET request, response + # status, content_type, body = do_stuff_with request + # + # response.status = status + # response['Content-Type'] = content_type + # response.body = body + # end + # + # def do_stuff_with request + # return 200, 'text/plain', 'you got a page' + # end + # end + # + # This servlet can be mounted on a server at a given path: + # + # server.mount '/simple', Simple + # + # == Servlet Configuration + # + # Servlets can be configured via initialize. The first argument is the + # HTTP server the servlet is being initialized for. + # + # class Configurable < Simple + # def initialize server, color, size + # super server + # @color = color + # @size = size + # end + # + # def do_stuff_with request + # content = "<p " \ + # %q{style="color: #{@color}; font-size: #{@size}"} \ + # ">Hello, World!" + # + # return 200, "text/html", content + # end + # end + # + # This servlet must be provided two arguments at mount time: + # + # server.mount '/configurable', Configurable, 'red', '2em' + class AbstractServlet - def self.get_instance(config, *options) - self.new(config, *options) + + ## + # Factory for servlet instances that will handle a request from +server+ + # using +options+ from the mount point. By default a new servlet + # instance is created for every call. + + def self.get_instance(server, *options) + self.new(server, *options) end + ## + # Initializes a new servlet for +server+ using +options+ which are + # stored as-is in +@options+. +@logger+ is also provided. + def initialize(server, *options) @server = @config = server @logger = @server[:Logger] @options = options end + ## + # Dispatches to a +do_+ method based on +req+ if such a method is + # available. (+do_GET+ for a GET request). Raises a MethodNotAllowed + # exception if the method is not implemented. + def service(req, res) method_name = "do_" + req.request_method.gsub(/-/, "_") if respond_to?(method_name) @@ -39,27 +109,38 @@ module WEBrick end end + ## + # Raises a NotFound exception + def do_GET(req, res) raise HTTPStatus::NotFound, "not found." end + ## + # Dispatches to do_GET + def do_HEAD(req, res) do_GET(req, res) end + ## + # Returns the allowed HTTP request methods + def do_OPTIONS(req, res) - m = self.methods.grep(/^do_[A-Z]+$/) - m.collect!{|i| i.sub(/do_/, "") } + m = self.methods.grep(/\Ado_([A-Z]+)\z/) {$1} m.sort! res["allow"] = m.join(",") end private + ## + # Redirects to a path ending in / + def redirect_to_directory_uri(req, res) if req.path[-1] != ?/ location = WEBrick::HTTPUtils.escape_path(req.path + "/") - if req.query_string && req.query_string.size > 0 + if req.query_string && req.query_string.bytesize > 0 location << "?" << req.query_string end res.set_redirect(HTTPStatus::MovedPermanently, location) diff --git a/lib/webrick/httpservlet/cgi_runner.rb b/lib/webrick/httpservlet/cgi_runner.rb index 006abd458e..0398c16749 100644 --- a/lib/webrick/httpservlet/cgi_runner.rb +++ b/lib/webrick/httpservlet/cgi_runner.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false # # cgi_runner.rb -- CGI launcher. # @@ -13,21 +14,20 @@ def sysread(io, size) while size > 0 tmp = io.sysread(size) buf << tmp - size -= tmp.size + size -= tmp.bytesize end return buf end STDIN.binmode -buf = "" len = sysread(STDIN, 8).to_i out = sysread(STDIN, len) -STDOUT.reopen(open(out, "w")) +STDOUT.reopen(File.open(out, "w")) len = sysread(STDIN, 8).to_i err = sysread(STDIN, len) -STDERR.reopen(open(err, "w")) +STDERR.reopen(File.open(err, "w")) len = sysread(STDIN, 8).to_i dump = sysread(STDIN, len) @@ -38,7 +38,7 @@ hash.each{|k, v| ENV[k] = v if v } dir = File::dirname(ENV["SCRIPT_FILENAME"]) Dir::chdir dir -if interpreter = ARGV[0] +if ARGV[0] argv = ARGV.dup argv << ENV["SCRIPT_FILENAME"] exec(*argv) diff --git a/lib/webrick/httpservlet/cgihandler.rb b/lib/webrick/httpservlet/cgihandler.rb index a35b59edb8..4457770b7a 100644 --- a/lib/webrick/httpservlet/cgihandler.rb +++ b/lib/webrick/httpservlet/cgihandler.rb @@ -1,61 +1,77 @@ -# +# frozen_string_literal: false +# # cgihandler.rb -- CGIHandler Class -# +# # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. -# +# # $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $ require 'rbconfig' require 'tempfile' -require 'webrick/config' -require 'webrick/httpservlet/abstract' +require_relative '../config' +require_relative 'abstract' module WEBrick module HTTPServlet + ## + # Servlet for handling CGI scripts + # + # Example: + # + # server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler, + # '/path/to/my_script') + class CGIHandler < AbstractServlet - Ruby = File::join(::Config::CONFIG['bindir'], - ::Config::CONFIG['ruby_install_name']) - Ruby << ::Config::CONFIG['EXEEXT'] - CGIRunner = "\"#{Ruby}\" \"#{Config::LIBDIR}/httpservlet/cgi_runner.rb\"" + Ruby = RbConfig.ruby # :nodoc: + CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc: + CGIRunnerArray = [Ruby, "#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb".freeze].freeze # :nodoc: + + ## + # Creates a new CGI script servlet for the script at +name+ def initialize(server, name) - super + super(server, name) @script_filename = name @tempdir = server[:TempDir] - @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}" + interpreter = server[:CGIInterpreter] + if interpreter.is_a?(Array) + @cgicmd = CGIRunnerArray + interpreter + else + @cgicmd = "#{CGIRunner} #{interpreter}" + end end - def do_GET(req, res) - data = nil - status = -1 + # :stopdoc: + def do_GET(req, res) cgi_in = IO::popen(@cgicmd, "wb") - cgi_out = Tempfile.new("webrick.cgiout.", @tempdir) - cgi_err = Tempfile.new("webrick.cgierr.", @tempdir) + cgi_out = Tempfile.new("webrick.cgiout.", @tempdir, mode: IO::BINARY) + cgi_out.set_encoding("ASCII-8BIT") + cgi_err = Tempfile.new("webrick.cgierr.", @tempdir, mode: IO::BINARY) + cgi_err.set_encoding("ASCII-8BIT") begin cgi_in.sync = true meta = req.meta_vars meta["SCRIPT_FILENAME"] = @script_filename meta["PATH"] = @config[:CGIPathEnv] + meta.delete("HTTP_PROXY") if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM meta["SystemRoot"] = ENV["SystemRoot"] end dump = Marshal.dump(meta) - cgi_in.write("%8d" % cgi_out.path.size) + cgi_in.write("%8d" % cgi_out.path.bytesize) cgi_in.write(cgi_out.path) - cgi_in.write("%8d" % cgi_err.path.size) + cgi_in.write("%8d" % cgi_err.path.bytesize) cgi_in.write(cgi_err.path) - cgi_in.write("%8d" % dump.size) + cgi_in.write("%8d" % dump.bytesize) cgi_in.write(dump) - if req.body and req.body.size > 0 - cgi_in.write(req.body) - end + req.body { |chunk| cgi_in.write(chunk) } ensure cgi_in.close status = $?.exitstatus @@ -63,19 +79,19 @@ module WEBrick data = cgi_out.read cgi_out.close(true) if errmsg = cgi_err.read - if errmsg.size > 0 + if errmsg.bytesize > 0 @logger.error("CGIHandler: #{@script_filename}:\n" + errmsg) end - end + end cgi_err.close(true) end - + if status != 0 @logger.error("CGIHandler: #{@script_filename} exit with #{status}") end data = "" unless data - raw_header, body = data.split(/^[\xd\xa]+/on, 2) + raw_header, body = data.split(/^[\xd\xa]+/, 2) raise HTTPStatus::InternalServerError, "Premature end of script headers: #{@script_filename}" if body.nil? @@ -85,6 +101,10 @@ module WEBrick res.status = $1.to_i header.delete('status') end + if header.has_key?('location') + # RFC 3875 6.2.3, 6.2.4 + res.status = 302 unless (300...400) === res.status + end if header.has_key?('set-cookie') header['set-cookie'].each{|k| res.cookies << Cookie.parse_set_cookie(k) @@ -98,6 +118,8 @@ module WEBrick res.body = body end alias do_POST do_GET + + # :startdoc: end end diff --git a/lib/webrick/httpservlet/erbhandler.rb b/lib/webrick/httpservlet/erbhandler.rb index b9d5e65b65..cd09e5f216 100644 --- a/lib/webrick/httpservlet/erbhandler.rb +++ b/lib/webrick/httpservlet/erbhandler.rb @@ -1,37 +1,63 @@ -# +# frozen_string_literal: false +# # erbhandler.rb -- ERBHandler Class -# +# # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. -# +# # $IPR: erbhandler.rb,v 1.25 2003/02/24 19:25:31 gotoyuzo Exp $ -require 'webrick/httpservlet/abstract.rb' +require_relative 'abstract' require 'erb' module WEBrick module HTTPServlet + ## + # ERBHandler evaluates an ERB file and returns the result. This handler + # is automatically used if there are .rhtml files in a directory served by + # the FileHandler. + # + # ERBHandler supports GET and POST methods. + # + # The ERB file is evaluated with the local variables +servlet_request+ and + # +servlet_response+ which are a WEBrick::HTTPRequest and + # WEBrick::HTTPResponse respectively. + # + # Example .rhtml file: + # + # Request to <%= servlet_request.request_uri %> + # + # Query params <%= servlet_request.query.inspect %> + class ERBHandler < AbstractServlet + + ## + # Creates a new ERBHandler on +server+ that will evaluate and serve the + # ERB file +name+ + def initialize(server, name) - super + super(server, name) @script_filename = name end + ## + # Handles GET requests + def do_GET(req, res) unless defined?(ERB) @logger.warn "#{self.class}: ERB not defined." raise HTTPStatus::Forbidden, "ERBHandler cannot work." end begin - data = open(@script_filename){|io| io.read } + data = File.open(@script_filename, &:read) res.body = evaluate(ERB.new(data), req, res) - res['content-type'] = + res['content-type'] ||= HTTPUtils::mime_type(@script_filename, @config[:MimeTypes]) - rescue StandardError => ex + rescue StandardError raise rescue Exception => ex @logger.error(ex) @@ -39,13 +65,21 @@ module WEBrick end end + ## + # Handles POST requests + alias do_POST do_GET private + + ## + # Evaluates +erb+ providing +servlet_request+ and +servlet_response+ as + # local variables. + def evaluate(erb, servlet_request, servlet_response) Module.new.module_eval{ - meta_vars = servlet_request.meta_vars - query = servlet_request.query + servlet_request.meta_vars + servlet_request.query erb.result(binding) } end diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb index 24f59d7142..7cac05d818 100644 --- a/lib/webrick/httpservlet/filehandler.rb +++ b/lib/webrick/httpservlet/filehandler.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false # # filehandler.rb -- FileHandler Module # @@ -8,22 +9,38 @@ # # $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $ -require 'thread' require 'time' -require 'webrick/htmlutils' -require 'webrick/httputils' -require 'webrick/httpstatus' +require_relative '../htmlutils' +require_relative '../httputils' +require_relative '../httpstatus' module WEBrick module HTTPServlet + ## + # Servlet for serving a single file. You probably want to use the + # FileHandler servlet instead as it handles directories and fancy indexes. + # + # Example: + # + # server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler, + # '/path/to/my_page.txt') + # + # This servlet handles If-Modified-Since and Range requests. + class DefaultFileHandler < AbstractServlet + + ## + # Creates a DefaultFileHandler instance for the file at +local_path+. + def initialize(server, local_path) - super + super(server, local_path) @local_path = local_path end + # :stopdoc: + def do_GET(req, res) st = File::stat(@local_path) mtime = st.mtime @@ -32,15 +49,15 @@ module WEBrick if not_modified?(req, res, mtime, res['etag']) res.body = '' raise HTTPStatus::NotModified - elsif req['range'] + elsif req['range'] make_partial_content(req, res, @local_path, st.size) raise HTTPStatus::PartialContent else mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes]) res['content-type'] = mtype - res['content-length'] = st.size + res['content-length'] = st.size.to_s res['last-modified'] = mtime.httpdate - res.body = open(@local_path, "rb") + res.body = File.open(@local_path, "rb") end end @@ -69,47 +86,66 @@ module WEBrick return false end + # returns a lambda for webrick/httpresponse.rb send_body_proc + def multipart_body(body, parts, boundary, mtype, filesize) + lambda do |socket| + begin + begin + first = parts.shift + last = parts.shift + socket.write( + "--#{boundary}#{CRLF}" \ + "Content-Type: #{mtype}#{CRLF}" \ + "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \ + "#{CRLF}" + ) + + begin + IO.copy_stream(body, socket, last - first + 1, first) + rescue NotImplementedError + body.seek(first, IO::SEEK_SET) + IO.copy_stream(body, socket, last - first + 1) + end + socket.write(CRLF) + end while parts[0] + socket.write("--#{boundary}--#{CRLF}") + ensure + body.close + end + end + end + def make_partial_content(req, res, filename, filesize) mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes]) unless ranges = HTTPUtils::parse_range_header(req['range']) raise HTTPStatus::BadRequest, "Unrecognized range-spec: \"#{req['range']}\"" end - open(filename, "rb"){|io| + File.open(filename, "rb"){|io| if ranges.size > 1 time = Time.now boundary = "#{time.sec}_#{time.usec}_#{Process::pid}" - body = '' - ranges.each{|range| - first, last = prepare_range(range, filesize) - next if first < 0 - io.pos = first - content = io.read(last-first+1) - body << "--" << boundary << CRLF - body << "Content-Type: #{mtype}" << CRLF - body << "Content-Range: #{first}-#{last}/#{filesize}" << CRLF - body << CRLF - body << content - body << CRLF + parts = [] + ranges.each {|range| + prange = prepare_range(range, filesize) + next if prange[0] < 0 + parts.concat(prange) } - raise HTTPStatus::RequestRangeNotSatisfiable if body.empty? - body << "--" << boundary << "--" << CRLF + raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty? res["content-type"] = "multipart/byteranges; boundary=#{boundary}" - res.body = body + if req.http_version < '1.1' + res['connection'] = 'close' + else + res.chunked = true + end + res.body = multipart_body(io.dup, parts, boundary, mtype, filesize) elsif range = ranges[0] first, last = prepare_range(range, filesize) raise HTTPStatus::RequestRangeNotSatisfiable if first < 0 - if last == filesize - 1 - content = io.dup - content.pos = first - else - io.pos = first - content = io.read(last-first+1) - end res['content-type'] = mtype - res['content-range'] = "#{first}-#{last}/#{filesize}" - res['content-length'] = last - first + 1 - res.body = content + res['content-range'] = "bytes #{first}-#{last}/#{filesize}" + res['content-length'] = (last - first + 1).to_s + res.body = io.dup else raise HTTPStatus::BadRequest end @@ -123,19 +159,47 @@ module WEBrick last = filesize - 1 if last >= filesize return first, last end + + # :startdoc: end + ## + # Serves a directory including fancy indexing and a variety of other + # options. + # + # Example: + # + # server.mount('/assets', WEBrick::HTTPServlet::FileHandler, + # '/path/to/assets') + class FileHandler < AbstractServlet - HandlerTable = Hash.new + HandlerTable = Hash.new # :nodoc: + + ## + # Allow custom handling of requests for files with +suffix+ by class + # +handler+ def self.add_handler(suffix, handler) HandlerTable[suffix] = handler end + ## + # Remove custom handling of requests for files with +suffix+ + def self.remove_handler(suffix) HandlerTable.delete(suffix) end + ## + # Creates a FileHandler servlet on +server+ that serves files starting + # at directory +root+ + # + # +options+ may be a Hash containing keys from + # WEBrick::Config::FileHandler or +true+ or +false+. + # + # If +options+ is true or false then +:FancyIndexing+ is enabled or + # disabled respectively. + def initialize(server, root, options={}, default=Config::FileHandler) @config = server.config @logger = @config[:Logger] @@ -146,9 +210,11 @@ module WEBrick @options = default.dup.update(options) end + # :stopdoc: + def service(req, res) # if this class is mounted on "/" and /~username is requested. - # we're going to override path informations before invoking service. + # we're going to override path information before invoking service. if defined?(Etc) && @options[:UserDir] && req.script_name.empty? if %r|^(/~([^/]+))| =~ req.path_info script_name, user = $1, $2 @@ -214,16 +280,20 @@ module WEBrick # character in URI notation. So the value of path_info should be # normalize before accessing to the filesystem. + # dirty hack for filesystem encoding; in nature, File.expand_path + # should not be used for path normalization. [Bug #3345] + path = req.path_info.dup.force_encoding(Encoding.find("filesystem")) if trailing_pathsep?(req.path_info) # File.expand_path removes the trailing path separator. # Adding a character is a workaround to save it. # File.expand_path("/aaa/") #=> "/aaa" # File.expand_path("/aaa/" + "x") #=> "/aaa/x" - expanded = File.expand_path(req.path_info + "x") + expanded = File.expand_path(path + "x") expanded.chop! # remove trailing "x" else - expanded = File.expand_path(req.path_info) + expanded = File.expand_path(path) end + expanded.force_encoding(req.path_info.encoding) req.path_info = expanded end @@ -374,11 +444,18 @@ module WEBrick } list.compact! - if d0 = req.query["N"]; idx = 0 - elsif d0 = req.query["M"]; idx = 1 - elsif d0 = req.query["S"]; idx = 2 - else d0 = "A" ; idx = 0 + query = req.query + + d0 = nil + idx = nil + %w[N M S].each_with_index do |q, i| + if d = query.delete(q) + idx ||= i + d0 ||= d + end end + d0 ||= "A" + idx ||= 0 d1 = (d0 == "A") ? "D" : "A" if d0 == "A" @@ -387,40 +464,68 @@ module WEBrick list.sort!{|a,b| b[idx] <=> a[idx] } end - res['content-type'] = "text/html" + namewidth = query["NameWidth"] + if namewidth == "*" + namewidth = nil + elsif !namewidth or (namewidth = namewidth.to_i) < 2 + namewidth = 25 + end + query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")} + type = "text/html" + case enc = Encoding.find('filesystem') + when Encoding::US_ASCII, Encoding::ASCII_8BIT + else + type << "; charset=\"#{enc.name}\"" + end + res['content-type'] = type + + title = "Index of #{HTMLUtils::escape(req.path)}" res.body = <<-_end_of_html_ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> - <HEAD><TITLE>Index of #{HTMLUtils::escape(req.path)}</TITLE></HEAD> + <HEAD> + <TITLE>#{title}</TITLE> + <style type="text/css"> + <!-- + .name, .mtime { text-align: left; } + .size { text-align: right; } + td { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } + table { border-collapse: collapse; } + tr th { border-bottom: 2px groove; } + //--> + </style> + </HEAD> <BODY> - <H1>Index of #{HTMLUtils::escape(req.path)}</H1> + <H1>#{title}</H1> _end_of_html_ - res.body << "<PRE>\n" - res.body << " <A HREF=\"?N=#{d1}\">Name</A> " - res.body << "<A HREF=\"?M=#{d1}\">Last modified</A> " - res.body << "<A HREF=\"?S=#{d1}\">Size</A>\n" - res.body << "<HR>\n" - + res.body << "<TABLE width=\"100%\"><THEAD><TR>\n" + res.body << "<TH class=\"name\"><A HREF=\"?N=#{d1}#{query}\">Name</A></TH>" + res.body << "<TH class=\"mtime\"><A HREF=\"?M=#{d1}#{query}\">Last modified</A></TH>" + res.body << "<TH class=\"size\"><A HREF=\"?S=#{d1}#{query}\">Size</A></TH>\n" + res.body << "</TR></THEAD>\n" + res.body << "<TBODY>\n" + + query.sub!(/\A&/, '?') list.unshift [ "..", File::mtime(local_path+"/.."), -1 ] list.each{ |name, time, size| if name == ".." dname = "Parent Directory" - elsif name.size > 25 - dname = name.sub(/^(.{23})(.*)/){ $1 + ".." } + elsif namewidth and name.size > namewidth + dname = name[0...(namewidth - 2)] << '..' else dname = name end - s = " <A HREF=\"#{HTTPUtils::escape(name)}\">#{dname}</A>" - s << " " * (30 - dname.size) - s << (time ? time.strftime("%Y/%m/%d %H:%M ") : " " * 22) - s << (size >= 0 ? size.to_s : "-") << "\n" + s = "<TR><TD class=\"name\"><A HREF=\"#{HTTPUtils::escape(name)}#{query if name.end_with?('/')}\">#{HTMLUtils::escape(dname)}</A></TD>" + s << "<TD class=\"mtime\">" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "</TD>" + s << "<TD class=\"size\">" << (size >= 0 ? size.to_s : "-") << "</TD></TR>\n" res.body << s } - res.body << "</PRE><HR>" + res.body << "</TBODY></TABLE>" + res.body << "<HR>" - res.body << <<-_end_of_html_ + res.body << <<-_end_of_html_ <ADDRESS> #{HTMLUtils::escape(@config[:ServerSoftware])}<BR> at #{req.host}:#{req.port} @@ -430,6 +535,7 @@ module WEBrick _end_of_html_ end + # :startdoc: end end end diff --git a/lib/webrick/httpservlet/prochandler.rb b/lib/webrick/httpservlet/prochandler.rb index 783cb27896..599ffc4340 100644 --- a/lib/webrick/httpservlet/prochandler.rb +++ b/lib/webrick/httpservlet/prochandler.rb @@ -1,22 +1,35 @@ -# +# frozen_string_literal: false +# # prochandler.rb -- ProcHandler Class -# +# # Author: IPR -- Internet Programming with Ruby -- writers # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou # Copyright (c) 2002 Internet Programming with Ruby writers. All rights # reserved. -# +# # $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $ -require 'webrick/httpservlet/abstract.rb' +require_relative 'abstract' module WEBrick module HTTPServlet + ## + # Mounts a proc at a path that accepts a request and response. + # + # Instead of mounting this servlet with WEBrick::HTTPServer#mount use + # WEBrick::HTTPServer#mount_proc: + # + # server.mount_proc '/' do |req, res| + # res.body = 'it worked!' + # res.status = 200 + # end + class ProcHandler < AbstractServlet + # :stopdoc: def get_instance(server, *options) self - end + end def initialize(proc) @proc = proc @@ -27,6 +40,7 @@ module WEBrick end alias do_POST do_GET + # :startdoc: end end |
