/tools/Ruby/lib/ruby/1.8/soap/rpc/cgistub.rb

http://github.com/agross/netopenspace · Ruby · 206 lines · 151 code · 40 blank · 15 comment · 6 complexity · 2a7d6c8ef02db032ac36434f9e2539a3 MD5 · raw file

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