source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/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: 3.9 KB
Line 
1#
2# Implements a simple HTTP-server by using John W. Small's ([email protected])
3# ruby-generic-server.
4#
5# Copyright (C) 2001, 2002, 2003 by Michael Neumann ([email protected])
6#
7# $Id: httpserver.rb 11708 2007-02-12 23:01:19Z shyouhei $
8#
9
10
11require "gserver"
12
13class HttpServer < GServer
14
15 ##
16 # handle_obj specifies the object, that receives calls to request_handler
17 # and ip_auth_handler
18 def initialize(handle_obj, port = 8080, host = DEFAULT_HOST, maxConnections = 4,
19 stdlog = $stdout, audit = true, debug = true)
20 @handler = handle_obj
21 super(port, host, maxConnections, stdlog, audit, debug)
22 end
23
24private
25
26 # Constants -----------------------------------------------
27
28 CRLF = "\r\n"
29 HTTP_PROTO = "HTTP/1.0"
30 SERVER_NAME = "HttpServer (Ruby #{RUBY_VERSION})"
31
32 DEFAULT_HEADER = {
33 "Server" => SERVER_NAME
34 }
35
36 ##
37 # Mapping of status code and error message
38 #
39 StatusCodeMapping = {
40 200 => "OK",
41 400 => "Bad Request",
42 403 => "Forbidden",
43 405 => "Method Not Allowed",
44 411 => "Length Required",
45 500 => "Internal Server Error"
46 }
47
48 # Classes -------------------------------------------------
49
50 class Request
51 attr_reader :data, :header, :method, :path, :proto
52
53 def initialize(data, method=nil, path=nil, proto=nil)
54 @header, @data = Table.new, data
55 @method, @path, @proto = method, path, proto
56 end
57
58 def content_length
59 len = @header['Content-Length']
60 return nil if len.nil?
61 return len.to_i
62 end
63
64 end
65
66 class Response
67 attr_reader :header
68 attr_accessor :body, :status, :status_message
69
70 def initialize(status=200)
71 @status = status
72 @status_message = nil
73 @header = Table.new
74 end
75 end
76
77
78 ##
79 # a case-insensitive Hash class for HTTP header
80 #
81 class Table
82 include Enumerable
83
84 def initialize(hash={})
85 @hash = hash
86 update(hash)
87 end
88
89 def [](key)
90 @hash[key.to_s.capitalize]
91 end
92
93 def []=(key, value)
94 @hash[key.to_s.capitalize] = value
95 end
96
97 def update(hash)
98 hash.each {|k,v| self[k] = v}
99 self
100 end
101
102 def each
103 @hash.each {|k,v| yield k.capitalize, v }
104 end
105
106 def writeTo(port)
107 each { |k,v| port << "#{k}: #{v}" << CRLF }
108 end
109 end # class Table
110
111
112 # Helper Methods ------------------------------------------
113
114 def http_header(header=nil)
115 new_header = Table.new(DEFAULT_HEADER)
116 new_header.update(header) unless header.nil?
117
118 new_header["Connection"] = "close"
119 new_header["Date"] = http_date(Time.now)
120
121 new_header
122 end
123
124 def http_date( aTime )
125 aTime.gmtime.strftime( "%a, %d %b %Y %H:%M:%S GMT" )
126 end
127
128 def http_resp(status_code, status_message=nil, header=nil, body=nil)
129 status_message ||= StatusCodeMapping[status_code]
130
131 str = ""
132 str << "#{HTTP_PROTO} #{status_code} #{status_message}" << CRLF
133 http_header(header).writeTo(str)
134 str << CRLF
135 str << body unless body.nil?
136 str
137 end
138
139 # Main Serve Loop -----------------------------------------
140
141 def serve(io)
142 # perform IP authentification
143 unless @handler.ip_auth_handler(io)
144 io << http_resp(403, "Forbidden")
145 return
146 end
147
148 # parse first line
149 if io.gets =~ /^(\S+)\s+(\S+)\s+(\S+)/
150 request = Request.new(io, $1, $2, $3)
151 else
152 io << http_resp(400, "Bad Request")
153 return
154 end
155
156 # parse HTTP headers
157 while (line=io.gets) !~ /^(\n|\r)/
158 if line =~ /^([\w-]+):\s*(.*)$/
159 request.header[$1] = $2.strip
160 end
161 end
162
163 io.binmode
164 response = Response.new
165
166 # execute request handler
167 @handler.request_handler(request, response)
168
169 # write response back to the client
170 io << http_resp(response.status, response.status_message,
171 response.header, response.body)
172
173 rescue Exception => e
174 io << http_resp(500, "Internal Server Error")
175 end
176
177end # class HttpServer
178
Note: See TracBrowser for help on using the repository browser.