path_router 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,6 @@
1
+ /*.gem
2
+ /.bundle
3
+ /Gemfile.lock
4
+ /pkg/*
5
+
6
+ /path_router.rb
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # see path_router.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ eventmachine (0.12.10)
6
+ proxymachine (1.2.4)
7
+ eventmachine (>= 0.12.10)
8
+ rspec (2.6.0)
9
+ rspec-core (~> 2.6.0)
10
+ rspec-expectations (~> 2.6.0)
11
+ rspec-mocks (~> 2.6.0)
12
+ rspec-core (2.6.4)
13
+ rspec-expectations (2.6.0)
14
+ diff-lcs (~> 1.1.2)
15
+ rspec-mocks (2.6.0)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ proxymachine
22
+ rspec
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ path_router
2
+ ===========
3
+
4
+ HTTP routing by URL path, built on the excellent [ProxyMachine](https://github.com/mojombo/proxymachine) by the GitHub guys.
5
+
6
+ GitHub uses ProxyMachine to service millions of git connections every day.
7
+
8
+
9
+ Install
10
+ -------
11
+
12
+ ```
13
+ gem install path_router # installs path_router and proxymachine
14
+ path_router init # creates example path_router.rb
15
+ vim path_router.rb # specify your backends and URL patterns
16
+ path_router # fire it up, optionally with -h host and -p port
17
+ ```
18
+
19
+ Routes
20
+ ------
21
+
22
+ See `example_path_router.rb` to get the general idea.
23
+
24
+ ```ruby
25
+ PathRouter::Router.instance.reset.tap do |r|
26
+
27
+ r.backends = {
28
+ rails: "127.0.0.1:3000", # default
29
+ static: "127.0.0.1:8080",
30
+ wordpress: "10.0.0.1:80",
31
+ }
32
+
33
+ r.connect :static,
34
+ %r{^/robots.txt},
35
+ %r{^/(?:images|stylesheets|javascripts)/}
36
+
37
+ r.connect :wordpress,
38
+ %r{^/blog/},
39
+ %r{^/feed}
40
+
41
+ end
42
+ ```
43
+
44
+ The only non-obvious point is that the first backend in the hash is the default catch-all.
45
+ Ruby 1.8 users get random default backend; think of it as an easter egg ;)
46
+
47
+
48
+ Tests
49
+ -----
50
+
51
+ ```
52
+ $ rspec spec/*_spec.rb
53
+
54
+ PathRouter::Router
55
+ routes by specified patterns
56
+ defaults to first backend for unmatched requests
57
+
58
+ Finished in 0.00056 seconds
59
+ 2 examples, 0 failures
60
+ ```
61
+
62
+
63
+ Meh.
64
+ ----
65
+
66
+ (c) 2011 Paul Annesley, MIT licence.
67
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/path_router ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+
5
+ BASEDIR = File.realpath(File.join(File.dirname(__FILE__), ".."))
6
+
7
+ if ARGV.include? "init"
8
+ require "fileutils"
9
+ dest = "./path_router.rb"
10
+ FileUtils.cp File.join(BASEDIR, "example_path_router.rb"), dest
11
+ puts "Created example #{dest}"
12
+ exit
13
+ end
14
+
15
+ args = [ "--config", File.join(BASEDIR, "proxymachine_config.rb") ]
16
+
17
+ OptionParser.new do |opts|
18
+ opts.banner = <<-EOF
19
+
20
+ path_router init
21
+ Creates example path_router.rb into the current directory.
22
+
23
+ path_router [-h <host>] [-p <port>]
24
+ Start ProxyMachine with path_router config loaded from path_router.rb in
25
+ the current directory.
26
+
27
+ Options:
28
+ EOF
29
+ opts.on("-hHOST", "--host HOST", "Hostname to bind. Default 0.0.0.0") do |host|
30
+ args += [ "--host", host ]
31
+ end
32
+ opts.on("-pPORT", "--port PORT", "Port to listen on. Default 5432") do |port|
33
+ args += [ "--port", port ]
34
+ end
35
+ end.parse!
36
+
37
+ exec "proxymachine", *args
@@ -0,0 +1,17 @@
1
+ PathRouter::Router.instance.reset.tap do |r|
2
+
3
+ r.backends = {
4
+ rails: "127.0.0.1:3000", # default
5
+ static: "127.0.0.1:8080",
6
+ wordpress: "10.0.0.1:80",
7
+ }
8
+
9
+ r.connect :static,
10
+ %r{^/robots.txt},
11
+ %r{^/(?:images|stylesheets|javascripts)/}
12
+
13
+ r.connect :wordpress,
14
+ %r{^/blog/},
15
+ %r{^/feed}
16
+
17
+ end
@@ -0,0 +1,46 @@
1
+ module PathRouter
2
+ class Router
3
+
4
+ def self.instance
5
+ @instance ||= new
6
+ end
7
+
8
+ def initialize
9
+ reset
10
+ end
11
+
12
+ def reset
13
+ @backends = {}
14
+ @routes = {}
15
+ self
16
+ end
17
+
18
+ def load_routes(file = "path_router.rb")
19
+ puts "Loading routes from #{file}"
20
+ load file
21
+ rescue LoadError => e
22
+ puts "Failed to load routes: " << e.message
23
+ end
24
+
25
+ # Hash of backends, { Regexp => "ip:port", ... }
26
+ def backends=(backends)
27
+ backends.default = backends.values.first
28
+ @backends = backends
29
+ end
30
+
31
+ # Connect patterns to the given backend.
32
+ def connect(backend, *patterns)
33
+ patterns.each { |p| @routes[p] = backend }
34
+ end
35
+
36
+ # method e.g. "GET", currently unused
37
+ # path e.g. "/some/path?including=query+string"
38
+ def lookup(method, path)
39
+ _, backend = @routes.detect do |pattern, _|
40
+ path =~ pattern
41
+ end
42
+ @backends[backend]
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module PathRouter
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ module PathRouter
2
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "path_router/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "path_router"
7
+ s.version = PathRouter::VERSION
8
+ s.authors = ["Paul Annesley"]
9
+ s.email = ["paul@annesley.cc"]
10
+ s.homepage = ""
11
+ s.summary = %q{HTTP routing by URL path, built on ProxyMachine.}
12
+ s.description = %q{Easily route HTTP requests to different backends by pattern matching the URL path.}
13
+
14
+ s.rubyforge_project = "path_router"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "proxymachine", "~> 1.2.4"
22
+ s.add_development_dependency "rspec"
23
+ end
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift "./lib"
2
+ require "path_router/router"
3
+
4
+ module PathRouter
5
+
6
+ Signal.trap("USR2") { Router.instance.load_routes }
7
+
8
+ Router.instance.load_routes
9
+
10
+ proxy do |data|
11
+ if data =~ %r{^(\w+) (\S+) HTTP/\d.\d\r\n}
12
+ { remote: Router.instance.lookup($1, $2) }
13
+ else
14
+ { noop: true }
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "spec_helper"
2
+
3
+ module PathRouter
4
+ describe Router do
5
+
6
+ let(:router) do
7
+ Router.new.tap do |r|
8
+
9
+ r.backends = {
10
+ rails: "127.0.0.1:3000",
11
+ static: "127.0.0.1:8080",
12
+ api: "api:80"
13
+ }
14
+
15
+ r.connect :static,
16
+ %r{^/robots.txt},
17
+ %r{^/(?:images|stylesheets|javascripts)/}
18
+
19
+ r.connect :api,
20
+ %r{^/api/}
21
+
22
+ end
23
+ end
24
+
25
+ it "routes by specified patterns" do
26
+ router.lookup("GET", "/robots.txt").should == "127.0.0.1:8080"
27
+ router.lookup("GET", "/images/logo.png").should == "127.0.0.1:8080"
28
+ router.lookup("GET", "/api/list").should == "api:80"
29
+ end
30
+
31
+ it "defaults to first backend for unmatched requests" do
32
+ router.lookup("GET", "/anything/else").should == "127.0.0.1:3000"
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift "./lib"
2
+
3
+ require "path_router/router"
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: path_router
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Annesley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-17 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: proxymachine
16
+ requirement: &2169316300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.2.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2169316300
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2169315880 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2169315880
36
+ description: Easily route HTTP requests to different backends by pattern matching
37
+ the URL path.
38
+ email:
39
+ - paul@annesley.cc
40
+ executables:
41
+ - path_router
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - .rspec
47
+ - Gemfile
48
+ - Gemfile.lock
49
+ - README.md
50
+ - Rakefile
51
+ - bin/path_router
52
+ - example_path_router.rb
53
+ - lib/path_router.rb
54
+ - lib/path_router/router.rb
55
+ - lib/path_router/version.rb
56
+ - path_router.gemspec
57
+ - proxymachine_config.rb
58
+ - spec/path_router_spec.rb
59
+ - spec/spec_helper.rb
60
+ homepage: ''
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project: path_router
80
+ rubygems_version: 1.8.5
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: HTTP routing by URL path, built on ProxyMachine.
84
+ test_files:
85
+ - spec/path_router_spec.rb
86
+ - spec/spec_helper.rb