]> code.delx.au - cgiproxy/blob - ruby/proxy.rb
Tabs to spaces
[cgiproxy] / ruby / proxy.rb
1 #!/usr/bin/env ruby
2
3 require 'net/http'
4 require 'net/https'
5 require 'uri'
6
7 class NilClass
8 # Make it easier to check for empty string or nil
9 def empty?; true; end
10 def to_s; ""; end
11 end
12
13
14 def get_params(url)
15 if !ENV["PATH_INFO"].empty?
16 url += ENV["PATH_INFO"]
17 end
18
19 url = URI.parse(url);
20 if !["http", "https"].include? url.scheme
21 raise RuntimeError, "Unsupported scheme: #{url.scheme}"
22 end
23
24 use_ssl = url.scheme == 'https'
25
26 filename = url.path.split("/")[-1]
27 path = url.path
28 if !ENV["QUERY_STRING"].empty?
29 path += "?" + ENV["QUERY_STRING"]
30 end
31
32 return url.host, url.port, use_ssl, filename, path
33 end
34
35 def add_header(req, env_key, header_key)
36 value = ENV[env_key]
37 if !value.empty?
38 req[header_key] = value
39 end
40 end
41
42 def create_request(method, path, ff_header)
43 if method == "GET"
44 req = Net::HTTP::Get.new(path)
45 elsif method == "POST"
46 req = Net::HTTP::Post.new(path)
47 req.body = $stdin.read()
48 else
49 raise RuntimeError, "No support for method: #{method}"
50 end
51
52 if ff_header
53 add_header(req, "REMOTE_ADDR", "X-Forwarded-For")
54 end
55 add_header(req, "HTTP_HOST", "Host")
56 add_header(req, "HTTP_COOKIE", "Cookie")
57 add_header(req, "HTTP_REFERER", "Referer")
58 add_header(req, "CONTENT_LENGTH", "Content-Length")
59 add_header(req, "CONTENT_TYPE", "Content-Type")
60 add_header(req, "HTTP_USER_AGENT", "User-Agent")
61 add_header(req, "HTTP_CACHE_CONTROL", "Cache-Control")
62 add_header(req, "HTTP_AUTHORIZATION", "Authorization")
63 add_header(req, "HTTP_ACCEPT", "Accept")
64 add_header(req, "HTTP_ACCEPT_CHARSET", "Accept-Charset")
65 add_header(req, "HTTP_ACCEPT_ENCODING", "Accept-Encoding")
66 add_header(req, "HTTP_ACCEPT_LANGUAGE", "Accept-Language")
67
68 return req
69 end
70
71 def do_proxy(req, host, port, use_ssl, filename, output_dir)
72 # Make the request
73 http = Net::HTTP.new(host, port)
74 http.use_ssl = use_ssl
75 res = http.request req do |res|
76
77 if res.code != "200"
78 res["Status"] = "#{res.code} #{res.message}"
79 end
80 res.each_capitalized_name do |key|
81 res.get_fields(key).each do |value|
82 $stdout.write "#{key}: #{value}\r\n"
83 end
84 end
85 $stdout.write "\r\n"
86
87 out = nil
88 if output_dir
89 out = File.open("#{output_dir}/#{filename}", 'w')
90 end
91 res.read_body do |chunk|
92 $stdout.write chunk
93 if out
94 out.write chunk
95 end
96 end
97 end
98 end
99
100 def debug(msg)
101 File.open("/tmp/debuglog.txt", "a") { |f|
102 f << Time.new.to_s + " " + msg + "\n"
103 }
104 end
105
106 def proxy_to(base_path, ff_header=True, output_dir=nil)
107 host, port, use_ssl, filename, path = get_params(base_path)
108 req = create_request(ENV["REQUEST_METHOD"], path, ff_header)
109 do_proxy(req, host, port, use_ssl, filename, output_dir)
110 end
111