1 | # SOAP4R - CGI/mod_ruby stub library
|
---|
2 | # Copyright (C) 2001, 2003-2005 NAKAMURA, Hiroshi <[email protected]>.
|
---|
3 |
|
---|
4 | # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
---|
5 | # redistribute it and/or modify it under the same terms of Ruby's license;
|
---|
6 | # either the dual license version in 2003, or any later version.
|
---|
7 |
|
---|
8 |
|
---|
9 | require 'soap/streamHandler'
|
---|
10 | require 'webrick/httpresponse'
|
---|
11 | require 'webrick/httpstatus'
|
---|
12 | require 'logger'
|
---|
13 | require 'soap/rpc/soaplet'
|
---|
14 |
|
---|
15 |
|
---|
16 | module SOAP
|
---|
17 | module RPC
|
---|
18 |
|
---|
19 |
|
---|
20 | ###
|
---|
21 | # SYNOPSIS
|
---|
22 | # CGIStub.new
|
---|
23 | #
|
---|
24 | # DESCRIPTION
|
---|
25 | # To be written...
|
---|
26 | #
|
---|
27 | class CGIStub < Logger::Application
|
---|
28 | include SOAP
|
---|
29 | include WEBrick
|
---|
30 |
|
---|
31 | class SOAPRequest
|
---|
32 | attr_reader :body
|
---|
33 |
|
---|
34 | def [](var); end
|
---|
35 |
|
---|
36 | def meta_vars; end
|
---|
37 | end
|
---|
38 |
|
---|
39 | class SOAPStdinRequest < SOAPRequest
|
---|
40 | attr_reader :body
|
---|
41 |
|
---|
42 | def initialize(stream)
|
---|
43 | size = ENV['CONTENT_LENGTH'].to_i || 0
|
---|
44 | @body = stream.read(size)
|
---|
45 | end
|
---|
46 |
|
---|
47 | def [](var)
|
---|
48 | ENV[var.gsub(/-/, '_').upcase]
|
---|
49 | end
|
---|
50 |
|
---|
51 | def meta_vars
|
---|
52 | {
|
---|
53 | 'HTTP_SOAPACTION' => ENV['HTTP_SOAPAction']
|
---|
54 | }
|
---|
55 | end
|
---|
56 | end
|
---|
57 |
|
---|
58 | class SOAPFCGIRequest < SOAPRequest
|
---|
59 | attr_reader :body
|
---|
60 |
|
---|
61 | def initialize(request)
|
---|
62 | @request = request
|
---|
63 | @body = @request.in.read
|
---|
64 | end
|
---|
65 |
|
---|
66 | def [](var)
|
---|
67 | @request.env[var.gsub(/-/, '_').upcase]
|
---|
68 | end
|
---|
69 |
|
---|
70 | def meta_vars
|
---|
71 | {
|
---|
72 | 'HTTP_SOAPACTION' => @request.env['HTTP_SOAPAction']
|
---|
73 | }
|
---|
74 | end
|
---|
75 | end
|
---|
76 |
|
---|
77 | def initialize(appname, default_namespace)
|
---|
78 | super(appname)
|
---|
79 | set_log(STDERR)
|
---|
80 | self.level = ERROR
|
---|
81 | @default_namespace = default_namespace
|
---|
82 | @remote_host = ENV['REMOTE_HOST'] || ENV['REMOTE_ADDR'] || 'unknown'
|
---|
83 | @router = ::SOAP::RPC::Router.new(self.class.name)
|
---|
84 | @soaplet = ::SOAP::RPC::SOAPlet.new(@router)
|
---|
85 | on_init
|
---|
86 | end
|
---|
87 |
|
---|
88 | def on_init
|
---|
89 | # do extra initialization in a derived class if needed.
|
---|
90 | end
|
---|
91 |
|
---|
92 | def mapping_registry
|
---|
93 | @router.mapping_registry
|
---|
94 | end
|
---|
95 |
|
---|
96 | def mapping_registry=(value)
|
---|
97 | @router.mapping_registry = value
|
---|
98 | end
|
---|
99 |
|
---|
100 | def generate_explicit_type
|
---|
101 | @router.generate_explicit_type
|
---|
102 | end
|
---|
103 |
|
---|
104 | def generate_explicit_type=(generate_explicit_type)
|
---|
105 | @router.generate_explicit_type = generate_explicit_type
|
---|
106 | end
|
---|
107 |
|
---|
108 | # servant entry interface
|
---|
109 |
|
---|
110 | def add_rpc_servant(obj, namespace = @default_namespace)
|
---|
111 | @router.add_rpc_servant(obj, namespace)
|
---|
112 | end
|
---|
113 | alias add_servant add_rpc_servant
|
---|
114 |
|
---|
115 | def add_headerhandler(obj)
|
---|
116 | @router.add_headerhandler(obj)
|
---|
117 | end
|
---|
118 | alias add_rpc_headerhandler add_headerhandler
|
---|
119 |
|
---|
120 | # method entry interface
|
---|
121 |
|
---|
122 | def add_rpc_method(obj, name, *param)
|
---|
123 | add_rpc_method_with_namespace_as(@default_namespace, obj, name, name, *param)
|
---|
124 | end
|
---|
125 | alias add_method add_rpc_method
|
---|
126 |
|
---|
127 | def add_rpc_method_as(obj, name, name_as, *param)
|
---|
128 | add_rpc_method_with_namespace_as(@default_namespace, obj, name, name_as, *param)
|
---|
129 | end
|
---|
130 | alias add_method_as add_rpc_method_as
|
---|
131 |
|
---|
132 | def add_rpc_method_with_namespace(namespace, obj, name, *param)
|
---|
133 | add_rpc_method_with_namespace_as(namespace, obj, name, name, *param)
|
---|
134 | end
|
---|
135 | alias add_method_with_namespace add_rpc_method_with_namespace
|
---|
136 |
|
---|
137 | def add_rpc_method_with_namespace_as(namespace, obj, name, name_as, *param)
|
---|
138 | qname = XSD::QName.new(namespace, name_as)
|
---|
139 | soapaction = nil
|
---|
140 | param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
|
---|
141 | @router.add_rpc_operation(obj, qname, soapaction, name, param_def)
|
---|
142 | end
|
---|
143 | alias add_method_with_namespace_as add_rpc_method_with_namespace_as
|
---|
144 |
|
---|
145 | def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
|
---|
146 | @router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
|
---|
147 | end
|
---|
148 |
|
---|
149 | def add_document_operation(receiver, soapaction, name, param_def, opt = {})
|
---|
150 | @router.add_document_operation(receiver, soapaction, name, param_def, opt)
|
---|
151 | end
|
---|
152 |
|
---|
153 | def set_fcgi_request(request)
|
---|
154 | @fcgi = request
|
---|
155 | end
|
---|
156 |
|
---|
157 | private
|
---|
158 |
|
---|
159 | HTTPVersion = WEBrick::HTTPVersion.new('1.0') # dummy; ignored
|
---|
160 |
|
---|
161 | def run
|
---|
162 | res = WEBrick::HTTPResponse.new({:HTTPVersion => HTTPVersion})
|
---|
163 | begin
|
---|
164 | @log.info { "received a request from '#{ @remote_host }'" }
|
---|
165 | if @fcgi
|
---|
166 | req = SOAPFCGIRequest.new(@fcgi)
|
---|
167 | else
|
---|
168 | req = SOAPStdinRequest.new($stdin)
|
---|
169 | end
|
---|
170 | @soaplet.do_POST(req, res)
|
---|
171 | rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
|
---|
172 | res.set_error(ex)
|
---|
173 | rescue HTTPStatus::Error => ex
|
---|
174 | res.set_error(ex)
|
---|
175 | rescue HTTPStatus::Status => ex
|
---|
176 | res.status = ex.code
|
---|
177 | rescue StandardError, NameError => ex # for Ruby 1.6
|
---|
178 | res.set_error(ex, true)
|
---|
179 | ensure
|
---|
180 | if defined?(MOD_RUBY)
|
---|
181 | r = Apache.request
|
---|
182 | r.status = res.status
|
---|
183 | r.content_type = res.content_type
|
---|
184 | r.send_http_header
|
---|
185 | buf = res.body
|
---|
186 | else
|
---|
187 | buf = ''
|
---|
188 | res.send_response(buf)
|
---|
189 | buf.sub!(/^[^\r]+\r\n/, '') # Trim status line.
|
---|
190 | end
|
---|
191 | @log.debug { "SOAP CGI Response:\n#{ buf }" }
|
---|
192 | if @fcgi
|
---|
193 | @fcgi.out.print buf
|
---|
194 | @fcgi.finish
|
---|
195 | @fcgi = nil
|
---|
196 | else
|
---|
197 | print buf
|
---|
198 | end
|
---|
199 | end
|
---|
200 | 0
|
---|
201 | end
|
---|
202 | end
|
---|
203 |
|
---|
204 |
|
---|
205 | end
|
---|
206 | end
|
---|