webrick_httpreverseproxyserver-FlipPath 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +23 -0
- data/Rakefile +30 -0
- data/lib/webrick/httpreverseproxyserver.rb +162 -0
- data/lib/webrick/httpreverseproxyserver/version.rb +5 -0
- metadata +72 -0
data/README.rdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= HTTP Reverse proxy server
|
2
|
+
|
3
|
+
This library is not meant for production use. It is based on a snippet on
|
4
|
+
RubyForge and was packaged as gem to make it easily available.
|
5
|
+
|
6
|
+
You may use this class, to programmatically set up a quick and simple reverse
|
7
|
+
proxy. I found it useful to implement advanced inspection of an HTTP
|
8
|
+
communication between an uncontrolled client and server.
|
9
|
+
|
10
|
+
== Documentation
|
11
|
+
|
12
|
+
See WEBrick::HTTPReverseProxyServer for more information.
|
13
|
+
|
14
|
+
|
15
|
+
== License
|
16
|
+
|
17
|
+
The code was originally released in 2006 by Richard Kernahan on Rubyforge.
|
18
|
+
|
19
|
+
http://rubyforge.org/snippet/detail.php?type=snippet&id=117
|
20
|
+
|
21
|
+
It was packaged as RubyGem by Gregor Schmidt.
|
22
|
+
|
23
|
+
The code is release under the terms of the Artistic License.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
$: << File.expand_path('../lib', __FILE__)
|
6
|
+
require 'webrick/httpreverseproxyserver/version'
|
7
|
+
|
8
|
+
desc 'Generate documentation for the webrick_httpreverseproxyserver gem.'
|
9
|
+
Rake::RDocTask.new(:doc) do |doc|
|
10
|
+
doc.rdoc_dir = 'doc'
|
11
|
+
doc.title = 'WEBRick::HTTPReverseProxyServer'
|
12
|
+
doc.options << '--line-numbers' << '--inline-source'
|
13
|
+
doc.rdoc_files.include('README.rdoc')
|
14
|
+
doc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Build gem'
|
18
|
+
task :build do
|
19
|
+
sh 'gem build webrick_httpreverseproxyserver.gemspec'
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Install gem locally"
|
23
|
+
task :install => :build do
|
24
|
+
sh "gem install webrick_httpreverseproxyserver-#{WEBrick::HTTPReverseProxyServer::VERSION}.gem"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Release gem'
|
28
|
+
task :release => :build do
|
29
|
+
sh "gem push webrick_httpreverseproxyserver-#{WEBrick::HTTPReverseProxyServer::VERSION}.gem"
|
30
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'webrick'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
module WEBrick
|
7
|
+
# Proxy rule to configure WEBrick::HTTPReverseProxyServer
|
8
|
+
class ProxyRule < Struct.new(:pattern, :host, :port, :replacement)
|
9
|
+
end
|
10
|
+
|
11
|
+
# == Use case
|
12
|
+
#
|
13
|
+
# You have several services running as different users for security purposes
|
14
|
+
# (they might even be chrooted). In production we use apache but for testing
|
15
|
+
# I prefer to use webrick because I find it more flexible for unit testing.
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# == Configuration
|
19
|
+
#
|
20
|
+
# The proxy mapping is modelled on the ProxyPass directive of apache. For
|
21
|
+
# example:
|
22
|
+
#
|
23
|
+
# original URL proxies private URL
|
24
|
+
# ------------------------ ==> --------------------------
|
25
|
+
# /marmalade/index.html localhost:8081/index.html
|
26
|
+
# /apps/vegemite?id=123 localhost:8082/apps/someservlet?id=123
|
27
|
+
#
|
28
|
+
# Its not designed to be mod_rewrite (eg. query_string cannot be
|
29
|
+
# transformed), but you can specify proxy rules that match a fragment of the
|
30
|
+
# original URL and replace it with something else while also sending the new
|
31
|
+
# URL to the proxied host and port. So the rules in that example are
|
32
|
+
# specified thus:
|
33
|
+
#
|
34
|
+
# serverConfig = {
|
35
|
+
# :Port => 80,
|
36
|
+
# :ProxyRules => [
|
37
|
+
# WEBrick::ProxyRule.new('^/marmalade/', 'localhost', 8081, '/'),
|
38
|
+
# WEBrick::ProxyRule.new('vegemite', 'localhost', 8082, 'someservlet')
|
39
|
+
# ]
|
40
|
+
# }
|
41
|
+
# server = WEBrick::HTTPReverseProxyServer.new(serverConfig)
|
42
|
+
#
|
43
|
+
# ProxyRules is an array so the order is important - the first match is used!
|
44
|
+
# If no matches are found then the URL is handled by the local web server
|
45
|
+
# normally.
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# == Running a server
|
49
|
+
#
|
50
|
+
# You may start a server, just like any WEBrick server.
|
51
|
+
#
|
52
|
+
# To get started using RubyGems, use the following example:
|
53
|
+
#
|
54
|
+
# require 'rubygems'
|
55
|
+
# require 'webrick/httpreverseproxyserver'
|
56
|
+
#
|
57
|
+
# # create a configuration and a server instance
|
58
|
+
# serverConfig = {
|
59
|
+
# :Port => 8080,
|
60
|
+
# :ProxyRules => [WEBrick::ProxyRule.new('/', 'www.example.com', 80, '/')]
|
61
|
+
# }
|
62
|
+
# server = WEBrick::HTTPReverseProxyServer.new(serverConfig)
|
63
|
+
#
|
64
|
+
# # catch ^C to quit cleanly
|
65
|
+
# trap("INT") { server.shutdown }
|
66
|
+
#
|
67
|
+
# # start request-response-loop
|
68
|
+
# server.start
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# == Advanced inspection
|
72
|
+
#
|
73
|
+
# In order to better analyse an HTTP stream, you may easily subclass
|
74
|
+
# HTTPReverseProxyServer to add advanced request/response inspection.
|
75
|
+
#
|
76
|
+
# The following example implements basic Cookie logging:
|
77
|
+
#
|
78
|
+
# class CookieLoggingProxy < WEBrick::HTTPReverseProxyServer
|
79
|
+
# def service(request, response)
|
80
|
+
# super.tap do
|
81
|
+
# puts
|
82
|
+
# puts request.request_line
|
83
|
+
# print_cookie_headers request.header
|
84
|
+
# puts response.status_line
|
85
|
+
# print_cookie_headers response.header
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# def print_cookie_headers(headers)
|
90
|
+
# headers.each do |key, val|
|
91
|
+
# puts "#{key}: #{val}" if key =~ /cookie/i
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
class HTTPReverseProxyServer < HTTPServer
|
96
|
+
def service(request, response)
|
97
|
+
rule = first_matching_proxy_rule(request)
|
98
|
+
if rule.nil?
|
99
|
+
super(request, response)
|
100
|
+
else
|
101
|
+
service_proxy(request, response, rule)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
# find the *first* matching pattern in the proxy map
|
107
|
+
def first_matching_proxy_rule(request)
|
108
|
+
matching_rule = @config[:ProxyRules].detect { |rule|
|
109
|
+
re = Regexp.new(rule.pattern)
|
110
|
+
m = re.match(request.path)
|
111
|
+
not m.nil?
|
112
|
+
}
|
113
|
+
return(matching_rule)
|
114
|
+
end
|
115
|
+
|
116
|
+
def service_proxy(request, res, rule)
|
117
|
+
host, port, path = map_to_proxyURI(request, rule)
|
118
|
+
# convert WEBrick header (values wrapped in an array) into Net::HTTP
|
119
|
+
# header (simple values)
|
120
|
+
header = {}
|
121
|
+
request.header.keys { |key| header[key] = request.header[key][0] }
|
122
|
+
header['x-forwarded-for'] = request.peeraddr[2] # the name of the requesting host
|
123
|
+
# send the new request to the private server (hacked from WEBrick::HTTPProxyServer)
|
124
|
+
response = nil
|
125
|
+
begin
|
126
|
+
http = Net::HTTP.new(host, port)
|
127
|
+
http.start {
|
128
|
+
case request.request_method
|
129
|
+
when "GET" then response = http.get(path, header)
|
130
|
+
when "POST" then response = http.post(path, request.body || "", header)
|
131
|
+
when "HEAD" then response = http.head(path, header)
|
132
|
+
else
|
133
|
+
raise HTTPStatus::MethodNotAllowed,
|
134
|
+
"unsupported method `#{request.request_method}'."
|
135
|
+
end
|
136
|
+
}
|
137
|
+
rescue => err
|
138
|
+
logger.debug("#{err.class}: #{err.message}")
|
139
|
+
raise HTTPStatus::ServiceUnavailable, err.message
|
140
|
+
end
|
141
|
+
res['connection'] = "close"
|
142
|
+
|
143
|
+
# Convert Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
|
144
|
+
res.status = response.code.to_i
|
145
|
+
res.each { |key, val| response[key] = val }
|
146
|
+
res.body = response.body
|
147
|
+
|
148
|
+
# Process contents
|
149
|
+
if handler = @config[:ProxyContentHandler]
|
150
|
+
handler.call(request, res)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def map_to_proxyURI(request, rule)
|
155
|
+
path = (request.path).sub(%r!#{rule.pattern}!, rule.replacement)
|
156
|
+
path += '?' + request.query_string if request.query_string
|
157
|
+
return([rule.host, rule.port, path])
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
require 'webrick/httpreverseproxyserver/version'
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webrick_httpreverseproxyserver-FlipPath
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Richard Kernahan
|
14
|
+
- Gregor Schmidt
|
15
|
+
- Shayne Sweeney
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-08-13 00:00:00 -07:00
|
21
|
+
default_executable:
|
22
|
+
dependencies: []
|
23
|
+
|
24
|
+
description: Implements a simple reverse HTTP proxy - useful for advanced configuration or inspection of reverse proxies in development.
|
25
|
+
email: g.schmidt@finn.de
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- lib/webrick/httpreverseproxyserver/version.rb
|
34
|
+
- lib/webrick/httpreverseproxyserver.rb
|
35
|
+
- Rakefile
|
36
|
+
- README.rdoc
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/FlipPath/webrick_httpreverseproxyserver
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
hash: 3
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project: "[none]"
|
67
|
+
rubygems_version: 1.3.7
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Implements a simple reverse HTTP proxy server
|
71
|
+
test_files: []
|
72
|
+
|