Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

root/branches/1_5/lib/soap/netHttpClient.rb

Revision 1920, 5.7 kB (checked in by nahi, 1 year ago)
  • soap4r without httpclient caused NameError?. forgot to add required dependency in the previous release. closes #403.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # SOAP4R - net/http wrapper
2 # Copyright (C) 2000-2007  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
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 'net/http'
10 require 'soap/filter/filterchain'
11
12
13 module SOAP
14
15
16 class NetHttpClient
17
18   SSLEnabled = begin
19       require 'net/https'
20       true
21     rescue LoadError
22       false
23     end
24
25   attr_reader :proxy
26   attr_accessor :no_proxy
27   attr_accessor :debug_dev
28   attr_accessor :ssl_config             # ignored for now.
29   attr_accessor :protocol_version       # ignored for now.
30   attr_accessor :connect_timeout
31   attr_accessor :send_timeout           # ignored for now.
32   attr_accessor :receive_timeout
33   attr_reader :test_loopback_response
34   attr_reader :request_filter           # ignored for now.
35
36   def initialize(proxy = nil, agent = nil)
37     @proxy = proxy ? URI.parse(proxy) : nil
38     @agent = agent
39     @debug_dev = nil
40     @test_loopback_response = []
41     @request_filter = Filter::FilterChain.new
42     @session_manager = SessionManager.new
43     @no_proxy = @ssl_config = @protocol_version = nil
44     @connect_timeout = @send_timeout = @receive_timeout = nil
45   end
46  
47   def proxy=(proxy)
48     if proxy.nil?
49       @proxy = nil
50     else
51       if proxy.is_a?(URI)
52         @proxy = proxy
53       else
54         @proxy = URI.parse(proxy)
55       end
56       if @proxy.scheme == nil or @proxy.scheme.downcase != 'http' or
57           @proxy.host == nil or @proxy.port == nil
58         raise ArgumentError.new("unsupported proxy `#{proxy}'")
59       end
60     end
61     reset_all
62     @proxy
63   end
64
65   def set_auth(uri, user_id, passwd)
66     raise NotImplementedError.new("auth is not supported under soap4r + net/http.")
67   end
68
69   def set_basic_auth(uri, user_id, passwd)
70     # net/http does not handle url.
71     @basic_auth = [user_id, passwd]
72     raise NotImplementedError.new("basic_auth is not supported under soap4r + net/http.")
73   end
74
75   def set_cookie_store(filename)
76     raise NotImplementedError.new
77   end
78
79   def save_cookie_store(filename)
80     raise NotImplementedError.new
81   end
82
83   def reset(url)
84     # no persistent connection.  ignored.
85   end
86
87   def reset_all
88     # no persistent connection.  ignored.
89   end
90
91   def post(url, req_body, header = {})
92     post_redirect(url, req_body, header, 10)
93   end
94
95   def get_content(url, header = {})
96     if str = @test_loopback_response.shift
97       return str
98     end
99     unless url.is_a?(URI)
100       url = URI.parse(url)
101     end
102     extra = header.dup
103     extra['User-Agent'] = @agent if @agent
104     res = start(url) { |http|
105         http.get(url.request_uri, extra)
106       }
107     res.body
108   end
109
110 private
111
112   def post_redirect(url, req_body, header, redirect_count)
113     if str = @test_loopback_response.shift
114       if @debug_dev
115         @debug_dev << "= Request\n\n"
116         @debug_dev << req_body
117         @debug_dev << "\n\n= Response\n\n"
118         @debug_dev << str
119       end
120       status = 200
121       reason = nil
122       contenttype = 'text/xml'
123       content = str
124       return Response.new(status, reason, contenttype, content)
125       return str
126     end
127     unless url.is_a?(URI)
128       url = URI.parse(url)
129     end
130     extra = header.dup
131     extra['User-Agent'] = @agent if @agent
132     res = start(url) { |http|
133       if @debug_dev
134         @debug_dev << "= Request\n\n"
135         @debug_dev << req_body << "\n"
136       end
137       http.post(url.request_uri, req_body, extra)
138     }
139     case res
140     when Net::HTTPRedirection
141       if redirect_count > 0
142         post_redirect(res['location'], req_body, header,
143           redirect_count - 1)
144       else
145        raise ArgumentError.new("Too many redirects")
146       end
147     else
148       Response.from_httpresponse(res)
149     end
150   end
151
152   def start(url)
153     http = create_connection(url)
154     response = nil
155     http.start { |worker|
156       response = yield(worker)
157       worker.finish
158     }
159     if @debug_dev
160       @debug_dev << "\n\n= Response\n\n"
161       @debug_dev << response.body << "\n"
162     end
163     response
164   end
165
166   def create_connection(url)
167     proxy_host = proxy_port = nil
168     unless no_proxy?(url)
169       proxy_host = @proxy.host
170       proxy_port = @proxy.port
171     end
172     http = Net::HTTP::Proxy(proxy_host, proxy_port).new(url.host, url.port)
173     if http.respond_to?(:set_debug_output)
174       http.set_debug_output(@debug_dev)
175     end
176     http.open_timeout = @connect_timeout if @connect_timeout
177     http.read_timeout = @receive_timeout if @receive_timeout
178     case url
179     when URI::HTTPS
180       if SSLEnabled
181         http.use_ssl = true
182       else
183         raise RuntimeError.new("Cannot connect to #{url} (OpenSSL is not installed.)")
184       end
185     when URI::HTTP
186       # OK
187     else
188       raise RuntimeError.new("Cannot connect to #{url} (Not HTTP.)")
189     end
190     http
191   end
192
193   NO_PROXY_HOSTS = ['localhost']
194
195   def no_proxy?(uri)
196     if !@proxy or NO_PROXY_HOSTS.include?(uri.host)
197       return true
198     end
199     unless @no_proxy
200       return false
201     end
202     @no_proxy.scan(/([^:,]+)(?::(\d+))?/) do |host, port|
203       if /(\A|\.)#{Regexp.quote(host)}\z/i =~ uri.host &&
204           (!port || uri.port == port.to_i)
205         return true
206       end
207     end
208     false
209   end
210
211   class SessionManager
212     attr_accessor :connect_timeout
213     attr_accessor :send_timeout
214     attr_accessor :receive_timeout
215   end
216
217   class Response
218     attr_reader :status
219     attr_reader :reason
220     attr_reader :contenttype
221     attr_reader :content
222
223     def initialize(status, reason, contenttype, content)
224       @status = status
225       @reason = reason
226       @contenttype = contenttype
227       @content = content
228     end
229
230     def self.from_httpresponse(res)
231       status = res.code.to_i
232       reason = res.message
233       contenttype = res['content-type']
234       content = res.body
235       new(status, reason, contenttype, content)
236     end
237   end
238 end
239
240
241 end
Note: See TracBrowser for help on using the browser.