proximity 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +6 -0
- data/lib/proximity/configuration.rb +26 -0
- data/lib/proximity/dsl.rb +23 -0
- data/lib/proximity/proxy.rb +35 -0
- data/lib/proximity/proxy_set.rb +60 -0
- data/lib/proximity/route_set.rb +31 -0
- data/lib/proximity/router.rb +48 -0
- data/lib/proximity/routes.rb +31 -0
- data/lib/proximity/utils.rb +13 -0
- data/lib/proximity/version.rb +3 -0
- data/lib/proximity.rb +62 -0
- data/proximity.gemspec +28 -0
- data/spec/proximity/proxy_set_spec.rb +82 -0
- data/spec/proximity/proxy_spec.rb +32 -0
- data/spec/proximity/route_set_spec.rb +10 -0
- data/spec/proximity/router_spec.rb +31 -0
- data/spec/proximity/routes_spec.rb +14 -0
- data/spec/proximity_spec.rb +41 -0
- data/spec/spec_helper.rb +33 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50d50c9dd93e7f7c305900b031fd2a309813fa3b
|
4
|
+
data.tar.gz: 7dc0a7fe4f64cbca804619630daef3cb283c1103
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8a7564c57cf8b7eb0b0db32fa592fba05d8ef2cfa96db70204b9165bde1da38869365ea9efeede63ca65d4df4f52f1d466bbb49fd7e37f54a17cd0b1f6866b81
|
7
|
+
data.tar.gz: 3f528ffeb8f9c21e2a774c8e0adaf683fb4bf4a361585d9a7cc11dd372b1b07f020be0ecabcc584ce5a3e48543707d6ac97762040e5cf50d6c73abc63d01f997
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Adam Hunter
|
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,49 @@
|
|
1
|
+
# Proximity
|
2
|
+
|
3
|
+
`Proximity` is a [`Rack::Proxy`](https://github.com/ncr/rack-proxy) router that uses
|
4
|
+
[`Journey`](https://github.com/rails/journey) for routing. `Journey` is
|
5
|
+
vendored into `ActionPack` as of [`Rails`](https://github.com/rails/rails/tree/master/actionpack/lib/action_dispatch/journey)4.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
1. Create your own subclass of `Rack::Proxy`.
|
9
|
+
2. `include Proximity` into that class.
|
10
|
+
3. Define `rewrite_env` and `rewrite_response` as normal. `Proximity`
|
11
|
+
overrides `Rack::Proxy`'s call so your `env['HTTP_HOST']` and
|
12
|
+
`env['PATH_INFO']` will be changed before your call to `rewrite_env`.
|
13
|
+
4. If you override `call`, ensure you call super.
|
14
|
+
5. Create your proxy routes in a `proxies.rb` file and require it in your
|
15
|
+
application.
|
16
|
+
|
17
|
+
## Example
|
18
|
+
```ruby
|
19
|
+
# my_proxy.rb
|
20
|
+
class MyProxy < RackProxy
|
21
|
+
include Proximity
|
22
|
+
end
|
23
|
+
|
24
|
+
# proxies.rb
|
25
|
+
MyProxy.routes.draw do
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
gem 'proximity'
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Or install it yourself as:
|
40
|
+
|
41
|
+
$ gem install proximity
|
42
|
+
|
43
|
+
## Contributing
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Proximity
|
2
|
+
module Configuration
|
3
|
+
|
4
|
+
def env
|
5
|
+
ENV['PROXIMITY_ENV'] ||= ENV['RACK_ENV'] || 'development'
|
6
|
+
end
|
7
|
+
|
8
|
+
def engine
|
9
|
+
ActionDispatch::Journey
|
10
|
+
end
|
11
|
+
|
12
|
+
def routesClass
|
13
|
+
engine.const_get(:Routes)
|
14
|
+
end
|
15
|
+
|
16
|
+
def routerClass
|
17
|
+
engine.const_get(:Router)
|
18
|
+
end
|
19
|
+
|
20
|
+
def pathPatternClass
|
21
|
+
engine.const_get(:Path).const_get(:Pattern)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Proximity
|
2
|
+
module Dsl
|
3
|
+
|
4
|
+
def dsl_exec(&block)
|
5
|
+
scope.instance_exec(&block) if block_given?
|
6
|
+
end
|
7
|
+
|
8
|
+
def scope
|
9
|
+
@scope ||= scopeClass.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def scopeClass
|
13
|
+
scopeModule = self.class.const_get(:Scope)
|
14
|
+
Class.new do
|
15
|
+
include scopeModule
|
16
|
+
attr_reader :set
|
17
|
+
def initialize(set)
|
18
|
+
@set = set
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Proximity
|
2
|
+
class Proxy
|
3
|
+
attr_accessor :source, :target, :format
|
4
|
+
|
5
|
+
def initialize(route_set)
|
6
|
+
@route_set = route_set
|
7
|
+
end
|
8
|
+
|
9
|
+
def target
|
10
|
+
with_format "#{route_set.target}#{@target == Same ? @source : @target}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def source
|
14
|
+
with_format "#{route_set.source}#{@source}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def pattern
|
18
|
+
Proximity.pathPatternClass.new(source)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class.name} target=#{target} source=#{source}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def with_format(url)
|
28
|
+
format.nil? ? url : "#{url}.#{format}"
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :route_set
|
32
|
+
|
33
|
+
Same = Class.new
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Proximity
|
2
|
+
class ProxySet
|
3
|
+
include Dsl
|
4
|
+
attr_accessor :route_set, :source, :target
|
5
|
+
|
6
|
+
def self.default_scheme
|
7
|
+
'http'
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(route_set, source, target)
|
11
|
+
self.route_set = route_set
|
12
|
+
self.source = source
|
13
|
+
self.target = target
|
14
|
+
end
|
15
|
+
|
16
|
+
def routes
|
17
|
+
route_set.routes
|
18
|
+
end
|
19
|
+
|
20
|
+
module Scope
|
21
|
+
def proxy(options)
|
22
|
+
Utils.stringify_keys!(options)
|
23
|
+
formats = options.delete('formats') || [options.delete('format')]
|
24
|
+
|
25
|
+
formats.each do |format|
|
26
|
+
set.routes.add_proxy set, *Utils.source_and_target(options), format
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def same
|
31
|
+
Proxy::Same
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def source=(value)
|
38
|
+
@source = normalize_source(value)
|
39
|
+
end
|
40
|
+
|
41
|
+
def target=(value)
|
42
|
+
@target = normalize_target(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def normalize_source(source)
|
46
|
+
source = source.starts_with?('/') ? source : "/#{source}"
|
47
|
+
source = source.ends_with?('/') ? source : "#{source}/"
|
48
|
+
end
|
49
|
+
|
50
|
+
def normalize_target(target)
|
51
|
+
uri = URI.parse(target)
|
52
|
+
target = uri.scheme.nil? ? "#{self.class.default_scheme}://#{target}" : target
|
53
|
+
env_tld target.ends_with?('/') ? target : "#{target}/"
|
54
|
+
end
|
55
|
+
|
56
|
+
def env_tld(url)
|
57
|
+
%w[development test].include?(Proximity.env) ? url.sub('.com', '.local') : url
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Proximity
|
2
|
+
class RouteSet
|
3
|
+
include Dsl
|
4
|
+
|
5
|
+
attr_accessor :router
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.router = Router.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def routes
|
12
|
+
router.routes
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw(&block)
|
16
|
+
dsl_exec(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def proxy_sets
|
20
|
+
@proxy_sets ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
module Scope
|
24
|
+
def route(prefixes, &block)
|
25
|
+
source, target = Utils.source_and_target(prefixes)
|
26
|
+
set.proxy_sets << ProxySet.new(set, source, target)
|
27
|
+
set.proxy_sets.last.dsl_exec(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Proximity
|
2
|
+
class Router
|
3
|
+
|
4
|
+
def routes
|
5
|
+
@routes ||= Routes.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def match(env)
|
9
|
+
matches = router.send :find_routes, env
|
10
|
+
Match.new(matches).presence
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#<#{self.class.name}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def router
|
20
|
+
@router ||= Proximity.routerClass.new(routes, {})
|
21
|
+
end
|
22
|
+
|
23
|
+
class Match
|
24
|
+
def initialize(matches)
|
25
|
+
@matches = matches
|
26
|
+
@match = matches.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def matches
|
30
|
+
@match[1]
|
31
|
+
end
|
32
|
+
|
33
|
+
def target
|
34
|
+
matches.inject(proxy.target) { |target, (key, value)|
|
35
|
+
target.gsub(":#{key}", value)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def proxy
|
40
|
+
@match[2].proxy
|
41
|
+
end
|
42
|
+
|
43
|
+
def presence
|
44
|
+
@matches.empty? ? nil : self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Proximity
|
2
|
+
class Routes < Proximity.routesClass
|
3
|
+
|
4
|
+
attr_reader :proxies
|
5
|
+
|
6
|
+
def [](index)
|
7
|
+
routes[index]
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_proxy(router, source, target, format)
|
11
|
+
proxy = Proxy.new(router)
|
12
|
+
proxy.source = source
|
13
|
+
proxy.target = target
|
14
|
+
proxy.format = format
|
15
|
+
|
16
|
+
route = add_route(app, proxy.pattern, {}, {})
|
17
|
+
route.extend(proxy_attr_module)
|
18
|
+
proxy.tap { |p| route.proxy = p }
|
19
|
+
end
|
20
|
+
|
21
|
+
def proxy_attr_module
|
22
|
+
@proxy_attr_module ||= Module.new { attr_accessor :proxy }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def app
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/proximity.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'action_dispatch/journey'
|
3
|
+
require 'active_support/core_ext/string/starts_ends_with'
|
4
|
+
|
5
|
+
require "proximity/version"
|
6
|
+
require "proximity/configuration"
|
7
|
+
|
8
|
+
module Proximity
|
9
|
+
extend Configuration
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.extend ClassMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def routes
|
17
|
+
@routes ||= RouteSet.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
route_env(env)
|
23
|
+
super
|
24
|
+
rescue RoutingError => e
|
25
|
+
headers = {'Content-Type' => 'text/plain', 'Content-Length' => e.message.length}
|
26
|
+
[404, headers, [e.message]]
|
27
|
+
end
|
28
|
+
|
29
|
+
def route_env(env)
|
30
|
+
host, path = route(env)
|
31
|
+
env.tap { |e|
|
32
|
+
e['SCRIPT_NAME'] = ''
|
33
|
+
e['HTTP_HOST'] = host
|
34
|
+
e['PATH_INFO'] = path
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def router
|
39
|
+
self.class.routes.router
|
40
|
+
end
|
41
|
+
|
42
|
+
def route(env)
|
43
|
+
match = router.match(env)
|
44
|
+
|
45
|
+
if match
|
46
|
+
uri = URI.parse(match.target)
|
47
|
+
[uri.host, uri.path]
|
48
|
+
else
|
49
|
+
raise RoutingError.new("The path: #{env['PATH_INFO']} does not match any proxy routes.")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
RoutingError = Class.new(StandardError)
|
54
|
+
end
|
55
|
+
|
56
|
+
require "proximity/dsl"
|
57
|
+
require "proximity/proxy"
|
58
|
+
require "proximity/proxy_set"
|
59
|
+
require "proximity/router"
|
60
|
+
require "proximity/routes"
|
61
|
+
require "proximity/route_set"
|
62
|
+
require "proximity/utils"
|
data/proximity.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'proximity/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "proximity"
|
8
|
+
spec.version = Proximity::VERSION
|
9
|
+
spec.authors = ["Adam Hunter", "Zach Colon"]
|
10
|
+
spec.email = ["adamhunter@me.com", "zcolon80@gmail.com"]
|
11
|
+
spec.description = %q[Rack::Proxy router using Journey]
|
12
|
+
spec.summary = %q[Proximity provides a router to applications utilizing Rack::Proxy to coordinate the source and target of a request.]
|
13
|
+
spec.homepage = "https://github.com/adamhunter/proximity"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "actionpack", "~> 4.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "rack-proxy"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Proximity::ProxySet do
|
4
|
+
let(:route_set) { mock_routes }
|
5
|
+
let(:router) { route_set.router }
|
6
|
+
let(:proxy_set) { route_set.proxy_sets.first }
|
7
|
+
let(:route) { router.routes.first }
|
8
|
+
let(:proxy) { route.proxy }
|
9
|
+
|
10
|
+
it "will set the source prefix on the route set" do
|
11
|
+
expect(proxy_set.source).to eq('/example/')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "will set the target prefix on the route set" do
|
15
|
+
expect(proxy_set.target).to eq('http://example.local/api/')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "will create a route with the given prefix for its source" do
|
19
|
+
expect(proxy.source).to eq('/example/active')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "will map the given prefix to the target prefix" do
|
23
|
+
expect(proxy.target).to eq('http://example.local/api/are/you/active')
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
describe "protocol" do
|
28
|
+
it "will be added to the target prefix if missing" do
|
29
|
+
expect(proxy_set.target).to eq('http://example.local/api/')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "will not add a protocol if provided in the target prefix" do
|
33
|
+
target = 'ftp://example.local/api/'
|
34
|
+
proxy_set = described_class.new(route_set, 'example', target)
|
35
|
+
expect(proxy_set.target).to eq(target)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "tld" do
|
40
|
+
before(:each) { Proximity.stub(:env).and_return(environment) }
|
41
|
+
after(:each) { ENV['PROXIMITY_ENV'] = 'test' }
|
42
|
+
|
43
|
+
context 'develepment' do
|
44
|
+
let(:environment) { 'development' }
|
45
|
+
|
46
|
+
it "will convert .com into .local" do
|
47
|
+
expect(proxy_set.target).to eq('http://example.local/api/')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'test' do
|
52
|
+
let(:environment) { 'test' }
|
53
|
+
|
54
|
+
it "will convert .com into .local" do
|
55
|
+
expect(proxy_set.target).to eq('http://example.local/api/')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'production' do
|
60
|
+
let(:environment) { 'production' }
|
61
|
+
|
62
|
+
it "will not convert .com into .local" do
|
63
|
+
expect(proxy_set.target).to eq('http://example.com/api/')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "formats" do
|
69
|
+
context "when given json and csv" do
|
70
|
+
let(:json) { router.routes[2].proxy }
|
71
|
+
let(:csv) { router.routes[3].proxy }
|
72
|
+
|
73
|
+
it "creates a route with a format of json" do
|
74
|
+
expect(json.format).to eq('json')
|
75
|
+
end
|
76
|
+
|
77
|
+
it "creates a route with a format of csv" do
|
78
|
+
expect(csv.format).to eq('csv')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Proximity::Proxy do
|
4
|
+
let(:router) { mock_routes }
|
5
|
+
let(:route) { router.routes[0].proxy }
|
6
|
+
let(:same) { router.routes[1].proxy }
|
7
|
+
let(:format) { router.routes[2].proxy }
|
8
|
+
|
9
|
+
it "prefixes the source with the route set source" do
|
10
|
+
expect(route.source).to eq('/example/active')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "prefixes the target with the route set target" do
|
14
|
+
expect(route.target).to eq('http://example.local/api/are/you/active')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "uses the source as the target if the target is Same" do
|
18
|
+
expect(same.target).to eq('http://example.local/api/count')
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "formats" do
|
22
|
+
it "will add the format precceeded by a dot to the source" do
|
23
|
+
expect(format.source).to eq('/example/accounts.json')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "will add the format precceeded by a dot to the target" do
|
27
|
+
expect(format.target).to eq('http://example.local/api/accounts.json')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Proximity::Router do
|
4
|
+
|
5
|
+
let(:route_set) { mock_routes }
|
6
|
+
let(:router) { route_set.router }
|
7
|
+
|
8
|
+
describe "parameters" do
|
9
|
+
let(:match) { router.match 'PATH_INFO' => '/example/accounts/157/members/8932' }
|
10
|
+
|
11
|
+
it "will properly parse path parameters from the input" do
|
12
|
+
expect(match.matches).to eq(account_id: '157', member_id: '8932')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "will properly bind path parameters to the output" do
|
16
|
+
expect(match.target).to eq('http://example.local/api/accounts-members/157-8932')
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "that do not match" do
|
20
|
+
let(:match) { router.match 'PATH_INFO' => '/lucy/in/the/sky/with/diamonds' }
|
21
|
+
subject { match }
|
22
|
+
it { should be_nil }
|
23
|
+
|
24
|
+
describe "but have the same prefix" do
|
25
|
+
let(:match) { router.match 'PATH_INFO' => '/example/accounts/157/panthers' }
|
26
|
+
it { should be_nil }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Proximity::Routes do
|
4
|
+
|
5
|
+
let(:routes) { described_class.new }
|
6
|
+
let(:router) { double('Router', source: 'foo', target: 'bar') }
|
7
|
+
|
8
|
+
it "adds the proxy to the route" do
|
9
|
+
proxy = routes.add_proxy(router, '/source', 'http://example.com/target', nil)
|
10
|
+
route = routes.first
|
11
|
+
expect(route.proxy).to eq proxy
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Proximity do
|
4
|
+
|
5
|
+
let(:proxy) { SpecProxy.new {} }
|
6
|
+
before(:each) { proxy.stub(:perform_request).and_return([200, {}, ['']]) }
|
7
|
+
|
8
|
+
it 'should have a version number' do
|
9
|
+
Proximity::VERSION.should_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "routing" do
|
13
|
+
let(:env) {
|
14
|
+
{
|
15
|
+
'SCRIPT_NAME' => __FILE__,
|
16
|
+
'PATH_INFO' => '/example/accounts/15',
|
17
|
+
'HTTP_HOST' => 'foobar.com',
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
let!(:response) { proxy.call(env) }
|
22
|
+
|
23
|
+
describe "script name" do
|
24
|
+
it "is set to blank" do
|
25
|
+
expect(env['SCRIPT_NAME']).to eq('')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "http host" do
|
30
|
+
it "is set based off the incoming route" do
|
31
|
+
expect(env['HTTP_HOST']).to eq('example.local')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "path name" do
|
36
|
+
it "is mapped based off the incoming route" do
|
37
|
+
expect(env['PATH_INFO']).to eq('/api/accounts/15')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'proximity'
|
3
|
+
require 'rack/proxy'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
class SpecProxy < Rack::Proxy
|
7
|
+
include Proximity
|
8
|
+
|
9
|
+
def self.routes
|
10
|
+
mock_routes
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def mock_routes
|
15
|
+
Proximity::RouteSet.new.tap { |r|
|
16
|
+
r.draw do
|
17
|
+
# self is RouteSet instance
|
18
|
+
route 'example' => 'example.com/api' do
|
19
|
+
# self is ProxySet instance
|
20
|
+
proxy 'active' => 'are/you/active'
|
21
|
+
proxy 'count' => same
|
22
|
+
proxy 'accounts' => same, formats: %w[json csv]
|
23
|
+
proxy 'accounts/:account_id' => same
|
24
|
+
proxy 'accounts/:account_id/members/:member_id' => 'accounts-members/:account_id-:member_id'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
RSpec.configure do |config|
|
32
|
+
config.order = :random
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proximity
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Hunter
|
8
|
+
- Zach Colon
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: actionpack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '4.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.3'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.3'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rack-proxy
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: pry
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
description: Rack::Proxy router using Journey
|
99
|
+
email:
|
100
|
+
- adamhunter@me.com
|
101
|
+
- zcolon80@gmail.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- .gitignore
|
107
|
+
- .rspec
|
108
|
+
- .travis.yml
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- lib/proximity.rb
|
114
|
+
- lib/proximity/configuration.rb
|
115
|
+
- lib/proximity/dsl.rb
|
116
|
+
- lib/proximity/proxy.rb
|
117
|
+
- lib/proximity/proxy_set.rb
|
118
|
+
- lib/proximity/route_set.rb
|
119
|
+
- lib/proximity/router.rb
|
120
|
+
- lib/proximity/routes.rb
|
121
|
+
- lib/proximity/utils.rb
|
122
|
+
- lib/proximity/version.rb
|
123
|
+
- proximity.gemspec
|
124
|
+
- spec/proximity/proxy_set_spec.rb
|
125
|
+
- spec/proximity/proxy_spec.rb
|
126
|
+
- spec/proximity/route_set_spec.rb
|
127
|
+
- spec/proximity/router_spec.rb
|
128
|
+
- spec/proximity/routes_spec.rb
|
129
|
+
- spec/proximity_spec.rb
|
130
|
+
- spec/spec_helper.rb
|
131
|
+
homepage: https://github.com/adamhunter/proximity
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.0.5
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: Proximity provides a router to applications utilizing Rack::Proxy to coordinate
|
155
|
+
the source and target of a request.
|
156
|
+
test_files:
|
157
|
+
- spec/proximity/proxy_set_spec.rb
|
158
|
+
- spec/proximity/proxy_spec.rb
|
159
|
+
- spec/proximity/route_set_spec.rb
|
160
|
+
- spec/proximity/router_spec.rb
|
161
|
+
- spec/proximity/routes_spec.rb
|
162
|
+
- spec/proximity_spec.rb
|
163
|
+
- spec/spec_helper.rb
|