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