rrproxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rrproxy.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Caleb Spare
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ rrproxy
2
+ =======
3
+
4
+ rrproxy ("routing reverse proxy" or "rockin' ruby proxy" -- you pick) is a very simple reverse proxy server
5
+ that can route requests to different servers based on simple pattern-matching rules against the requests. It
6
+ is intended for use in a development environment as a substitute for 'real' proxies (nginx/HAProxy/whatever)
7
+ that you use in production.
8
+
9
+ Installation
10
+ ------------
11
+
12
+ $ gem install rrproxy
13
+
14
+ rrproxy requires Ruby 1.9 (because it's based on Goliath).
15
+
16
+ Usage
17
+ -----
18
+
19
+ rrproxy takes a very simple Ruby configuration file.
20
+
21
+ [
22
+ ["/styles/screen.css", "localhost:8000"],
23
+ ["", "example.com"]
24
+ ]
25
+
26
+ As you can probably guess, this will redirect requests for example.com's css file to a local server (while
27
+ passing all other requests through normally).
28
+
29
+ Here's a more complicated example (it's also in `examples/example_config.rb`):
30
+
31
+ [
32
+ ["/foo/bar?special=true", "localhost:1234"], # Route this specific request to a local server
33
+ [%r{^(/foo).*}, "google.com", ""], # You can use a regex, and also replace the match with a third arg
34
+ ["", "amazon.com"] # Empty string matches everything
35
+ ]
36
+
37
+ You will provide an array of tuples, where each one is of the form
38
+
39
+ [pattern, target_host, <optional replacement string>]
40
+
41
+ For each request, rrproxy will examine each routing rule in order, checking for a prefix match (if the pattern
42
+ is a string) or a regex match. The first match found will be used, and the host for the request will be
43
+ changed to the corresponding target host. If a replacement is provided, it will be used as a substitute for
44
+ the first regex matching group (if the pattern is a regex) or the whole pattern (if the pattern is a string).
45
+
46
+ Credits
47
+ -------
48
+
49
+ * @tobert for the idea to use Goliath
50
+ * The PostRank folks for a kickass server framework
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/rrproxy ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "trollop"
4
+ require "dedent"
5
+ require "colorize"
6
+
7
+ require "rrproxy"
8
+
9
+ # The goliath folks really need to take a page out of Sinatra's book and provide an easy way to start up a
10
+ # server manually without using all their application runner and option parsing shit (in Sinatra terms,
11
+ # 'sinatra' vs 'sinatra/base'). As it is I had to poke around the source code a while to figure out all the
12
+ # little things necessary to make it work.
13
+
14
+ # See https://github.com/postrank-labs/goliath/blob/master/lib/goliath/runner.rb
15
+ def create_logger
16
+ logger = Log4r::Logger.new("rrproxy")
17
+ log_format = Log4r::PatternFormatter.new(:pattern => "[%d : %l] %m")
18
+ logger.add(Log4r::StdoutOutputter.new("console", :formatter => log_format))
19
+ logger.level = Log4r::INFO
20
+ logger
21
+ end
22
+
23
+ options = Trollop.options do
24
+ banner <<-EOS.dedent
25
+ rrproxy is a very simple reverse http proxy that can route requests based on pattern-matching the
26
+ URI. The configuration file is Ruby, and it must have the following form:
27
+
28
+ [
29
+ ["/foo/bar?special=true", "localhost:1234"], # Route this specific request to a local server
30
+ [%r{^(/foo).*}, "google.com", ""], # You can use a regex, and also replace the match
31
+ ["", "amazon.com"] # Empty string matches everything
32
+ ]
33
+
34
+ Usage:
35
+
36
+ $ rrproxy [options] CONFIG_FILE
37
+
38
+ where [options] are:
39
+ EOS
40
+ opt :address, "Bind address", :default => "0.0.0.0"
41
+ opt :port, "Port", :default => 9876
42
+ end
43
+
44
+ Trollop.die "You must provide a configuration file" unless ARGV[0]
45
+ Trollop.die "Invalid config file: #{ARGV[0]}" unless File.file? ARGV[0]
46
+ begin
47
+ RRProxy.routes = eval(File.read(ARGV[0]))
48
+ rescue
49
+ Trollop.die "Error reading or parsing the config file #{ARGV[0]}"
50
+ end
51
+
52
+ logger = create_logger
53
+ logger.info "Starting rrproxy (powered by Goliath) on #{options[:address]}:#{options[:port]}".green
54
+ RRProxy.routes.each do |route|
55
+ pattern, target, replacement = route
56
+ message = "Proxying `#{pattern}` to #{target}"
57
+ message << " and replacing pattern matches with `#{replacement}`" if replacement
58
+ logger.info message.green
59
+ end
60
+
61
+ Goliath.env = :development
62
+ api = RRProxy.new
63
+ server = Goliath::Server.new(options[:address], options[:port])
64
+ server.logger = logger
65
+ server.api = api
66
+ server.app = Goliath::Rack::Builder.build(RRProxy, api)
67
+ server.plugins = []
68
+ server.start
@@ -0,0 +1,8 @@
1
+ # General form: An array of
2
+ # [pattern, target_host, <optional replacement string>]
3
+
4
+ [
5
+ ["/foo/bar?special=true", "localhost:1234"], # Route this specific request to a local server
6
+ [%r{^(/foo).*}, "google.com", ""], # You can use a regex, and also replace the match with a third arg
7
+ ["", "amazon.com"] # Empty string matches everything
8
+ ]
data/lib/rrproxy.rb ADDED
@@ -0,0 +1,54 @@
1
+ require "goliath/api"
2
+ require "goliath/goliath"
3
+ require "goliath/rack"
4
+ require "goliath/server"
5
+ require "log4r"
6
+ require "em-synchrony/em-http"
7
+
8
+ class RRProxy < Goliath::API
9
+ class << self
10
+ attr_accessor :routes
11
+ end
12
+
13
+ use Goliath::Rack::Params
14
+
15
+ def options_parser(option_parser, options)
16
+ option_parser.on("-c", "--config CONFIG_FILE", "Ruby routes configuration file") do |filename|
17
+ options[:config] = filename
18
+ end
19
+ abort "asdf" unless File.file?(options[:config])
20
+ end
21
+
22
+ def on_headers(env, headers) env["untampered_headers"] = headers end
23
+
24
+ def response(env)
25
+ uri = env["REQUEST_URI"]
26
+ method = env["REQUEST_METHOD"]
27
+ logger.info "Proxying #{method} #{uri}"
28
+ method = method.downcase.to_sym
29
+ RRProxy.routes.each do |pattern, target, replacement|
30
+ if pattern.is_a?(Regexp)
31
+ next unless uri =~ pattern
32
+ uri.sub!($1, replacement) if replacement
33
+ else
34
+ next unless uri.start_with? pattern
35
+ uri.sub!(pattern, replacement) if replacement
36
+ end
37
+
38
+ target_url = "http://#{target}#{uri}"
39
+ headers = env["untampered_headers"]
40
+ headers["HOST"] = target
41
+ params = { :head => headers }
42
+ params[:body] = env["params"] if [:put, :post, :patch].include? method
43
+
44
+ http = EM::HttpRequest.new(target_url).send(method, params)
45
+ response_headers = {}
46
+ http.response_header.each do |k, v|
47
+ response_headers[k.downcase.split("_").map(&:capitalize).join("-")] = v
48
+ end
49
+
50
+ return [http.response_header.status, response_headers, [http.response]]
51
+ end
52
+ [503, {}, "No target specified for this path."]
53
+ end
54
+ end
data/rrproxy.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.authors = ["Caleb Spare"]
3
+ gem.email = ["cespare@gmail.com"]
4
+ gem.description = %q{rrproxy is a very simple routing reverse proxy written in Ruby.}
5
+ gem.summary = %q{A routing reverse proxy.}
6
+ gem.homepage = ""
7
+
8
+ gem.files = `git ls-files`.split($\)
9
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
10
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
11
+ gem.name = "rrproxy"
12
+ gem.version = "0.0.1"
13
+ gem.require_paths = ["lib"]
14
+
15
+ gem.add_dependency "goliath"
16
+ gem.add_dependency "log4r"
17
+ gem.add_dependency "em-http-request"
18
+ gem.add_dependency "trollop"
19
+ gem.add_dependency "dedent"
20
+ gem.add_dependency "colorize"
21
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rrproxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Caleb Spare
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-16 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: goliath
16
+ requirement: &24235400 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *24235400
25
+ - !ruby/object:Gem::Dependency
26
+ name: log4r
27
+ requirement: &24200780 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *24200780
36
+ - !ruby/object:Gem::Dependency
37
+ name: em-http-request
38
+ requirement: &24199760 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *24199760
47
+ - !ruby/object:Gem::Dependency
48
+ name: trollop
49
+ requirement: &24197520 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *24197520
58
+ - !ruby/object:Gem::Dependency
59
+ name: dedent
60
+ requirement: &24196100 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *24196100
69
+ - !ruby/object:Gem::Dependency
70
+ name: colorize
71
+ requirement: &24194600 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *24194600
80
+ description: rrproxy is a very simple routing reverse proxy written in Ruby.
81
+ email:
82
+ - cespare@gmail.com
83
+ executables:
84
+ - rrproxy
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - .gitignore
89
+ - Gemfile
90
+ - LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - bin/rrproxy
94
+ - example/example_config.rb
95
+ - lib/rrproxy.rb
96
+ - rrproxy.gemspec
97
+ homepage: ''
98
+ licenses: []
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.10
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: A routing reverse proxy.
121
+ test_files: []