]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/httputil.rb
Sat Jul 30 01:19:32 BST 2005 Tom Gilbert <tom@linuxbrit.co.uk>
[user/henk/code/ruby/rbot.git] / lib / rbot / httputil.rb
1 module Irc
2
3 require 'resolv'
4 require 'net/http'
5 Net::HTTP.version_1_2
6   
7 # class for making http requests easier (mainly for plugins to use)
8 # this class can check the bot proxy configuration to determine if a proxy
9 # needs to be used, which includes support for per-url proxy configuration.
10 class HttpUtil
11     BotConfig.register('http.proxy', :default => false,
12       :desc => "Proxy server to use for HTTP requests (URI, e.g http://proxy.host:port)")
13     BotConfig.register('http.proxy_user', :default => false,
14       :desc => "User for authenticating with the http proxy (if required)")
15     BotConfig.register('http.proxy_pass', :default => false,
16       :desc => "Password for authenticating with the http proxy (if required)")
17     BotConfig.register('http.proxy_include', :type => :array, :default => [],
18       :desc => "List of regexps to check against a URI's hostname/ip to see if we should use the proxy to access this URI. All URIs are proxied by default if the proxy is set, so this is only required to re-include URIs that might have been excluded by the exclude list. e.g. exclude /.*\.foo\.com/, include bar\.foo\.com")
19     BotConfig.register('http.proxy_exclude', :type => :array, :default => [],
20       :desc => "List of regexps to check against a URI's hostname/ip to see if we should use avoid the proxy to access this URI and access it directly")
21
22   def initialize(bot)
23     @bot = bot
24     @headers = {
25       'User-Agent' => "rbot http util #{$version} (http://linuxbrit.co.uk/rbot/)",
26     }
27   end
28
29   # if http_proxy_include or http_proxy_exclude are set, then examine the
30   # uri to see if this is a proxied uri
31   # the in/excludes are a list of regexps, and each regexp is checked against
32   # the server name, and its IP addresses
33   def proxy_required(uri)
34     use_proxy = true
35     if @bot.config["http.proxy_exclude"].empty? && @bot.config["http.proxy_include"].empty?
36       return use_proxy
37     end
38
39     list = [uri.host]
40     begin
41       list.push Resolv.getaddresses(uri.host)
42     rescue StandardError => err
43       puts "warning: couldn't resolve host uri.host"
44     end
45
46     unless @bot.config["http.proxy_exclude"].empty?
47       re = @bot.config["http.proxy_exclude"].collect{|r| Regexp.new(r)}
48       re.each do |r|
49         list.each do |item|
50           if r.match(item)
51             use_proxy = false
52             break
53           end
54         end
55       end
56     end
57     unless @bot.config["http.proxy_include"].empty?
58       re = @bot.config["http.proxy_include"].collect{|r| Regexp.new(r)}
59       re.each do |r|
60         list.each do |item|
61           if r.match(item)
62             use_proxy = true
63             break
64           end
65         end
66       end
67     end
68     debug "using proxy for uri #{uri}?: #{use_proxy}"
69     return use_proxy
70   end
71
72   # uri:: Uri to create a proxy for
73   #
74   # return a net/http Proxy object, which is configured correctly for
75   # proxying based on the bot's proxy configuration. 
76   # This will include per-url proxy configuration based on the bot config
77   # +http_proxy_include/exclude+ options.
78   def get_proxy(uri)
79     proxy = nil
80     if (ENV['http_proxy'])
81       proxy = URI.parse ENV['http_proxy']
82     end
83     if (@bot.config["http.proxy"])
84       proxy = URI.parse ENV['http_proxy']
85     end
86
87     if proxy
88       debug "proxy is set to #{proxy.uri}"
89       proxy = nil unless proxy_required(uri)
90     end
91     
92     proxy_host = nil
93     proxy_port = nil
94     proxy_user = nil
95     proxy_pass = nil
96     if @bot.config["http.proxy_user"]
97       proxy_user = @bot.config["http.proxy_user"]
98       if @bot.config["http.proxy_pass"]
99         proxy_pass = @bot.config["http.proxy_pass"]
100       end
101     end
102     if proxy
103       proxy_host = proxy.host
104       proxy_port = proxy.port
105     end
106     
107     return Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port, proxy_user, proxy_port)
108   end
109
110   # uri::         uri to query (Uri object)
111   # readtimeout:: timeout for reading the response
112   # opentimeout:: timeout for opening the connection
113   #
114   # simple get request, returns response body if the status code is 200 and
115   # the request doesn't timeout.
116   def get(uri, readtimeout=10, opentimeout=5)
117     proxy = get_proxy(uri)
118     proxy.open_timeout = opentimeout
119     proxy.read_timeout = readtimeout
120    
121     begin
122       proxy.start() {|http|
123         resp = http.get(uri.request_uri(), @headers)
124         if resp.code == "200"
125           return resp.body
126         else
127           puts "HttpUtil.get return code #{resp.code} #{resp.body}"
128         end
129         return nil
130       }
131     rescue StandardError, Timeout::Error => e
132       $stderr.puts "HttpUtil.get exception: #{e}, while trying to get #{uri}"
133     end
134     return nil
135   end
136 end
137
138 end