auto_response 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source :rubygems
2
+ gem 'listen'
3
+ gem 'colorize'
4
+ gem 'daemons'
5
+
6
+ group :test do
7
+ gem 'test-unit'
8
+ end
9
+
10
+ group :development do
11
+ gem 'gem-this'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ colorize (0.5.8)
5
+ daemons (1.1.9)
6
+ listen (0.6.0)
7
+ test-unit (2.5.3)
8
+
9
+ PLATFORMS
10
+ ruby
11
+
12
+ DEPENDENCIES
13
+ colorize
14
+ daemons
15
+ listen
16
+ test-unit
data/bin/ar ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require 'daemons'
3
+
4
+ START_SCRIPT = File.dirname(__FILE__) + '/start_ar.rb'
5
+
6
+ Daemons.run START_SCRIPT
data/bin/start_ar.rb ADDED
@@ -0,0 +1,5 @@
1
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
2
+
3
+ require 'autoresponse'
4
+
5
+ AutoResp::AutoResponder.new.start
data/lib/ar/parser.rb ADDED
@@ -0,0 +1,50 @@
1
+ module AutoResp
2
+
3
+ module Parser
4
+
5
+ require 'net/http'
6
+
7
+ def parse( str )
8
+
9
+ headers, body = {}, []
10
+ to_find_header, body_start = true, false
11
+
12
+ str.lines.each_with_index do |line, idx|
13
+ if to_find_header and not body_start
14
+ if line =~ /^\s*$/
15
+ if idx == 0
16
+ to_find_header = false
17
+ body << line
18
+ else
19
+ body_start = true
20
+ body = []
21
+ end
22
+ else
23
+ body << line
24
+ name, value = parse_header_item(line)
25
+ if name
26
+ headers[name] = value
27
+ else
28
+ to_find_header = false
29
+ end
30
+ end
31
+ else
32
+ body << line
33
+ end
34
+ end
35
+
36
+ headers = nil unless to_find_header and body_start
37
+ res_body = body.join
38
+
39
+ [headers, res_body]
40
+ end
41
+
42
+ def parse_header_item(str)
43
+ mtc = str.match /^\s*(\S+)\s*:\s*(\S.*)$/
44
+ [mtc[1], mtc[2]] if mtc
45
+ end
46
+
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,102 @@
1
+ require 'webrick/httpproxy'
2
+ require 'webrick/log'
3
+
4
+ require_relative 'rule_manager'
5
+ require_relative 'parser'
6
+
7
+ module AutoResp
8
+
9
+ class ProxyServer < WEBrick::HTTPProxyServer
10
+
11
+ include Parser
12
+
13
+ def initialize(core, config={})
14
+ @core = core
15
+ super(config.update({
16
+ :AccessLog => [],
17
+ :Logger => WEBrick::Log.new("/dev/null")
18
+ }))
19
+ end
20
+
21
+ def service(req, res)
22
+ header, body, status = find_auto_res(req.unparsed_uri)
23
+ res.status = status if status
24
+
25
+ if header or body
26
+ puts "match".ljust(8) << ": #{req.unparsed_uri}"
27
+ puts "header".ljust(8) << ": #{header}"
28
+ puts "body".ljust(8) << ": \n#{body}"
29
+ puts "-"*50
30
+ res.header.merge!(header || {})
31
+ res.body = body
32
+ else
33
+ super(req, res)
34
+ end
35
+ end
36
+
37
+ def find_auto_res(url)
38
+ @core.rules.find do |tar, map|
39
+ if trim_url(tar) === trim_url(url)
40
+ return fetch(map, tar, url)
41
+ end
42
+ end
43
+ end
44
+
45
+ def fetch(txt, declare, uri)
46
+
47
+ case txt
48
+ when Proc
49
+ mtc = uri.match(declare) if Regexp === declare
50
+ fetch( txt.call(*mtc), declare, uri )
51
+ when String
52
+ if goto = redirect_path(txt)
53
+ if is_uri?(goto)
54
+ Net::HTTP.get_response(URI(goto)) do |res|
55
+ return [nil, res.body]
56
+ end
57
+ elsif File.exist?(goto)
58
+ return parse(IO.read(goto))
59
+ end
60
+ else
61
+ parse(txt)
62
+ end
63
+ when Fixnum
64
+ [{}, "", txt]
65
+ when Array
66
+ [txt[1], txt[2], txt[0]]
67
+ end
68
+ end
69
+
70
+ private
71
+ def redirect_path(t)
72
+ if is_single_line?(t)
73
+ (t.match(/^=GOTO=> (\S.*?)\s*$/) || [] )[1]
74
+ end
75
+ end
76
+
77
+ def is_uri?(txt)
78
+ /^[A-Za-z][A-Za-z0-9+\-\.]*:\/\/.+/ =~ txt
79
+ end
80
+
81
+ def header_hash(header)
82
+ h = header.to_hash
83
+ h.each do |n,v|
84
+ h[n] = v.join if Array === v
85
+ end
86
+ end
87
+
88
+ def trim_url(url)
89
+ if url.is_a? String
90
+ url.sub(/\/$/, '')
91
+ else
92
+ url
93
+ end
94
+ end
95
+
96
+ def is_single_line?(text)
97
+ text.count("\n") < 2
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,16 @@
1
+ module AutoResp
2
+
3
+ module RuleDSL
4
+ def url(target, &block)
5
+ add_rule(target, &block);
6
+ end
7
+
8
+ def r(resp)
9
+ add_handler( resp )
10
+ end
11
+
12
+ def goto(url)
13
+ add_handler '=GOTO=> ' << url
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ require_relative 'rule_dsl'
2
+
3
+ module AutoResp
4
+
5
+ class RuleManager
6
+
7
+ include RuleDSL
8
+
9
+ def initialize
10
+ end
11
+
12
+ def rules
13
+ @rules ||= {}
14
+ end
15
+
16
+ def clear
17
+ @rules.clear
18
+ end
19
+
20
+ def add_handler( handler )
21
+ if @last_rule
22
+ rules[@last_rule] = handler
23
+ end
24
+ end
25
+
26
+ def add_rule(*args, &block)
27
+ @last_rule = target = args.first
28
+ case target
29
+ when Hash
30
+ @last_rule = target.keys.first
31
+ rules.merge! target
32
+ when String
33
+ rules[target] = args[1]
34
+ when Regexp
35
+ if block_given?
36
+ rules[target] = block
37
+ else
38
+ rules[target] = args[1]
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,118 @@
1
+ require 'xmlrpc/httpserver'
2
+ require 'open-uri'
3
+ require 'fileutils'
4
+ require 'listen'
5
+ require 'colorize'
6
+
7
+ require_relative 'ar/proxyserver'
8
+ require_relative 'ar/rule_manager'
9
+ require_relative 'ar/parser'
10
+
11
+ module AutoResp
12
+
13
+
14
+ class AutoResponder
15
+
16
+ ARHOME = "#{ENV["HOME"]}/.auto_response"
17
+ RULES = "#{ARHOME}/rules"
18
+
19
+ def initialize(config={})
20
+ @config = config
21
+ @rule_manager = RuleManager.new
22
+ init_autoresponse_home
23
+ init_proxy_server
24
+ load_rules
25
+ monitor_rules_change
26
+ end
27
+
28
+ protected
29
+ def init_autoresponse_home
30
+ unless File.exist?(RULES)
31
+ pwd = File.expand_path('..', File.dirname(__FILE__))
32
+ FileUtils.mkdir_p(ARHOME)
33
+ FileUtils.cp "#{pwd}/rules.sample", RULES
34
+ end
35
+ end
36
+
37
+ protected
38
+ def init_proxy_server
39
+ @server = ProxyServer.new(
40
+ self,
41
+ :BindAddress => @config[:host] || '0.0.0.0',
42
+ :Port => @config[:port] || 9000
43
+ )
44
+ trap('INT') { stop_and_exit }
45
+ end
46
+
47
+ public
48
+ def start
49
+ @thread = Thread.new { @server.start }
50
+ @thread.join
51
+ end
52
+
53
+ def stop_and_exit
54
+ stop
55
+ exit
56
+ end
57
+
58
+ def stop
59
+ puts "\nshuting down"
60
+ @server.shutdown
61
+ @thread.kill
62
+ end
63
+
64
+ def add_rule(*args, &block)
65
+ case args.first
66
+ when Hash
67
+ rules.merge! args.first
68
+ when String
69
+ rules[args[0]] = args[1]
70
+ when Regexp
71
+ if block_given?
72
+ rules[args[0]] = block
73
+ else
74
+ rules[args[0]] = args[1]
75
+ end
76
+ end
77
+ end
78
+
79
+ def rules
80
+ @rule_manager.rules
81
+ end
82
+
83
+ def clear_rules
84
+ rules.clear
85
+ end
86
+
87
+ private
88
+ def load_rules(path=nil)
89
+ path ||= @config[:rule_config]
90
+ path ||= "#{ARHOME}/rules"
91
+ if File.readable?(path)
92
+ @rule_manager.instance_eval File.read(path)
93
+ end
94
+ log_rules
95
+ end
96
+
97
+ def log_rules
98
+ puts "mapping rules:"
99
+ rules.each do |n,v|
100
+ puts n.to_s.ljust(30).green << "=> #{v}"
101
+ end
102
+ end
103
+
104
+ def monitor_rules_change
105
+ listener = Listen.to(ARHOME)
106
+ listener.change { reload_rules }
107
+ Thread.new { listener.start }
108
+ end
109
+
110
+ def reload_rules
111
+ @rule_manager.clear
112
+ load_rules
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+
data/readme.md ADDED
@@ -0,0 +1,87 @@
1
+ # AutoResponse - HTTP debugging tool for Linux and Mac
2
+
3
+ ## What's auto_response for?
4
+
5
+ [Fiddler](http://www.fiddler2.com) is the favor tool of many web developers for debugging HTTP web apps. However it is only available on Windows. AutoResponse ports the most used feature of fiddler, 'auto respond', to Linux and Mac world.
6
+
7
+ Auto_response acts as a proxy server like Fiddler does, allowing you to modify the content of HTTP response.
8
+
9
+ ## Quick start
10
+
11
+ 1. Install and run
12
+
13
+ gem install 'auto_response'
14
+ ar start
15
+
16
+ ar status #check server status
17
+ ar stop #stop proxy server
18
+
19
+ 2. Set your browser proxy to 'http://127.0.0.1:9000'
20
+ 3. Edit the configuration file to modify the urls you want change the response.
21
+
22
+ By default, the configuration file is located at:
23
+ `$HOME/.auto_response/rules`
24
+
25
+ ## Response rules
26
+
27
+ ~~~ruby
28
+ # Examples:
29
+
30
+ # just respond with status number
31
+ url "http://www.catchme.com"
32
+ r 404
33
+
34
+ # if you want to respond all requests with url
35
+ # equals "http://www.1688.com" with "Hello world!" :
36
+ url "http://www.1688.com"
37
+ r "Hello world"
38
+
39
+ # or you can respond with Array
40
+ url "http://china.alibaba.com"
41
+ r [200, {}, "Got replaced"] #[status, header, body]
42
+
43
+ # if you want to respond these requests with a file:
44
+ # this url will be responded with content of somefile.txt
45
+ # you can set headers and body in 'somefile.txt'
46
+ url "http://www.yousite.com"
47
+ goto "/home/youruser/somefile.txt"
48
+
49
+ # redirect to another url
50
+ url "http://www.targetsite.com"
51
+ goto "http://www.real-request-target.com/test.html"
52
+
53
+ # respond with text setting headers
54
+ url "http://www.target-site.com/target-url"
55
+ r <<-RESP
56
+ Test-Msg : http-header-example
57
+ header-server : Auto-Responder
58
+ Content-Type : text/html; charset=utf-8
59
+
60
+ <!Doctype html>
61
+ <html><body><h1>Hello world!</h1></body></html>
62
+ RESP
63
+
64
+ # match with regexp
65
+ url %r{http://pnq\.cc}
66
+ r "Any request made to pnq.cc will be responded with this message."
67
+
68
+ # regular expression and params
69
+ url %r{http://anysite\.cc(.*)} do |uri, path|
70
+ <<-RESP
71
+ Content-Type : text/html; charset=utf-8
72
+
73
+ <style>
74
+ body { font-size: 50pt; }
75
+ em { color: #ff7300; }
76
+ small { color: #ccc; }
77
+ </style>
78
+
79
+ With regular expression, you can do more powerful things. <br/>
80
+ You're requesting <em>#{path}</em> <br/>
81
+ <small>Server time is #{Time.now} now. </small>
82
+ RESP
83
+ end
84
+ ~~~
85
+
86
+ ## TODO:
87
+ * GUI monitor showing sessions
data/rules.sample ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # This is the AutoResponse rule config file
3
+ # using ruby syntax
4
+
5
+ # Examples:
6
+
7
+ # if you want to respond all requests with url
8
+ # equals "http://www.1688.com" with "Hello world!" :
9
+ url "http://www.1688.com"
10
+ r "Hello world"
11
+
12
+ # or you can respond with Array
13
+ url "http://china.alibaba.com"
14
+ r [200, {}, "Got replaced"] #[status, header, body]
15
+
16
+ # if you want to respond these requests with a file:
17
+ url "http://www.yousite.com"
18
+ goto "/home/youruser/somefile.txt"
19
+
20
+ # on Windows:
21
+ url "http://www.another-site.com"
22
+ goto "C:/Program\ Files/proj/test.txt"
23
+
24
+ # if you want to respond with another remote url:
25
+ url "http://www.targetsite.com"
26
+ goto "http://www.real-request-target.com/test.html"
27
+
28
+ # you can set response headers in the returned string
29
+ # e.g.
30
+ url "http://www.target-site.com/target-url"
31
+ r <<-RESP
32
+ Test-Msg : http-header-example
33
+ header-server : Auto-Responder
34
+ Content-Type : text/html; charset=utf-8
35
+
36
+ <!Doctype html>
37
+ <html><body><h1>Hello world!</h1></body></html>
38
+ RESP
39
+
40
+ # just respond with status number
41
+ url "http://www.catchme.com"
42
+ r 404
43
+
44
+ # Example of using regexp
45
+ url %r{http://pnq\.cc}
46
+ r "Any request made to pnq.cc will be responded with this message."
47
+
48
+ # Regular expression and params
49
+ url %r{http://anysite\.cc(.*)} do |uri, path|
50
+ <<-RESP
51
+ Content-Type : text/html; charset=utf-8
52
+
53
+ <style>
54
+ body { font-size: 50pt; }
55
+ em { color: #ff7300; }
56
+ small { color: #ccc; }
57
+ </style>
58
+
59
+ With regular expression, you can do more powerful things. <br/>
60
+ You're requesting <em>#{path}</em> <br/>
61
+ <small>Server time is #{Time.now} now. </small>
62
+ RESP
63
+ end
data/test/all-test.rb ADDED
@@ -0,0 +1,32 @@
1
+ gem 'test-unit'
2
+ require 'test/unit'
3
+ require 'test/unit/testsuite'
4
+ require 'test/unit/ui/console/testrunner'
5
+
6
+ require_relative 'respond_with_file_test'
7
+ require_relative 'respond_with_string_test'
8
+ require_relative 'respond_with_url_test'
9
+ require_relative 'respond_with_array_test'
10
+ require_relative 'respond_with_number_test'
11
+ require_relative 'match_with_reg_test'
12
+ require_relative 'response_text_parser_test'
13
+
14
+ class ALLTests < Test::Unit::TestSuite
15
+
16
+ def self.suite
17
+ tests = Test::Unit::TestSuite.new
18
+
19
+ tests << ParserTest.suite
20
+ tests << TestRespondWithString.suite
21
+ tests << TestRespondWithFile.suite
22
+ tests << TestRespondWithURL.suite
23
+ tests << TestRespondWithArray.suite
24
+ tests << TestRespondWithStatusCode.suite
25
+ tests << TestMatchWithReg.suite
26
+
27
+ tests
28
+ end
29
+ end
30
+
31
+
32
+ Test::Unit::UI::Console::TestRunner.run( ALLTests )
@@ -0,0 +1 @@
1
+ Hello world!
@@ -0,0 +1,3 @@
1
+ root:x:0:0:root:/root:/bin/bash
2
+ daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3
+ bin:x:2:2:bin:/bin:/bin/sh
data/test/helper.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'test/unit'
2
+ require 'net/http'
3
+ require_relative '../lib/autoresponse'
4
+
5
+ FIXTURE = File.expand_path("fixture", File.dirname(__FILE__))
6
+
7
+ module ARProxyTest
8
+
9
+ def setup
10
+ @ar = start_proxy_server('127.0.0.1', 8764)
11
+ @req = Net::HTTP::Proxy('127.0.0.1', 8764)
12
+ end
13
+
14
+ def start_proxy_server(host, port)
15
+ @ar = AutoResp::AutoResponder.new :host => host, :port => port
16
+ Thread.new {
17
+ @ar.start
18
+ @ar.clear_rules
19
+ }
20
+ sleep 0.1
21
+ @ar
22
+ end
23
+
24
+ def teardown
25
+ stop_proxy_server
26
+ end
27
+
28
+ def stop_proxy_server
29
+ @ar.stop
30
+ end
31
+
32
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'helper'
2
+
3
+ class TestMatchWithReg < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_with_parts
8
+ @ar.add_rule %r(http://books.cc/(.*)/(.*)) do |uri, cat, page|
9
+ "cat: #{cat}; page: #{page}"
10
+ end
11
+ @req.start('books.cc') do |http|
12
+ http.request_get('/books/1') do |res|
13
+ assert_equal 'cat: books; page: 1', res.body
14
+ assert_equal "200", res.code
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'helper'
2
+
3
+ class TestRespondWithArray < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_respond_with_good_status_array
8
+ @ar.add_rule 'http://www.test.com/' => [200, nil, 'test']
9
+ @req.start('www.test.com') do |http|
10
+ http.request_get('/') do |res|
11
+ assert_equal( nil, res.header["test"])
12
+ assert_equal 'test', res.body
13
+ assert_equal "200", res.code
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_respond_with_404_status_array
19
+ @ar.add_rule 'http://www.1688.com' => [404, nil, 'test']
20
+ @req.start('www.1688.com') do |http|
21
+ http.request_get('/') do |res|
22
+ assert_equal( nil, res.header["test"])
23
+ assert_equal 'test', res.body
24
+ assert_equal "404", res.code
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ require_relative 'helper'
2
+
3
+ class TestRespondWithFile < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_respond_with_simple_file
8
+ @ar.add_rule 'http://www.test.com/' => "=GOTO=> #{FIXTURE}/passwd"
9
+ @req.start('www.test.com') do |http|
10
+ http.request_get('/') do |res|
11
+ assert_equal IO.read("#{FIXTURE}/passwd"), res.body
12
+ end
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'helper'
2
+
3
+ class TestRespondWithStatusCode < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_respond_with_500
8
+ @ar.add_rule 'http://www.163.com/' => 500
9
+ @req.start('www.163.com') do |http|
10
+ http.request_get('/') do |res|
11
+ assert_equal "500", res.code
12
+ end
13
+ end
14
+ end
15
+
16
+ def test_respond_with_404
17
+ @ar.add_rule 'http://www.163.com' => 404
18
+ @req.start('www.163.com') do |http|
19
+ http.request_get('/') do |res|
20
+ assert_equal "404", res.code
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'helper'
2
+
3
+ class TestRespondWithString < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_respond_with_simple_string
8
+ @ar.add_rule 'http://www.test.com/' => 'test'
9
+ @req.start('www.test.com') do |http|
10
+ http.request_get('/') do |res|
11
+ assert_equal( nil, res.header["test"])
12
+ assert_equal 'test', res.body
13
+ end
14
+ end
15
+ end
16
+
17
+ def test_respond_uri_without_slash_with_simple_string
18
+ @ar.add_rule 'http://www.1688.com' => 'test'
19
+ @req.start('www.1688.com') do |http|
20
+ http.request_get('/') do |res|
21
+ assert_equal( nil, res.header["test"])
22
+ assert_equal 'test', res.body
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_respond_with_header_and_body
28
+ response = %Q(server: autoresponder\nname: hello\n \ntest)
29
+ @ar.add_rule 'http://www.1688.com/test' => response
30
+ @req.start('www.1688.com') do |http|
31
+ http.request_get('/test') do |res|
32
+ assert_equal( "autoresponder", res.header["server"])
33
+ assert_equal( "hello", res.header["name"])
34
+ assert_equal 'test', res.body
35
+ end
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'helper'
2
+
3
+ class TestRespondWithURL < Test::Unit::TestCase
4
+
5
+ include ARProxyTest
6
+
7
+ def test_respond_with_simple_file
8
+ @ar.add_rule 'http://www.test.com/' => '=GOTO=> http://www.1688.com/crossdomain.xml'
9
+ @req.start('www.test.com') do |http|
10
+ http.request_get('/') do |res|
11
+ open("http://www.1688.com/crossdomain.xml") do |file|
12
+ assert_equal file.read, res.read_body
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'helper'
2
+
3
+ class ParserTest < Test::Unit::TestCase
4
+
5
+ include AutoResp::Parser
6
+
7
+ def test_parse_only_body
8
+ headers, body = parse("test")
9
+ assert_equal nil, headers
10
+ assert_equal "test", body
11
+ end
12
+
13
+ def test_parse_only_header
14
+ headers, body = parse("test: good\n\n")
15
+ assert_equal({"test" => "good"}, headers)
16
+ assert body.empty?
17
+ end
18
+
19
+ def test_parse_header
20
+ headers, body = parse("test: good\n\ncontent")
21
+ assert_equal({"test"=>"good"}, headers)
22
+ assert_equal "content", body
23
+ end
24
+
25
+ def test_first_line_empty
26
+ headers, body = parse(" \ntest: good\n\ncontent")
27
+ assert_equal nil, headers
28
+ assert_equal " \ntest: good\n\ncontent", body
29
+ end
30
+
31
+ def test_empty_line_in_middle
32
+ response = %Q(server: autoresponder\ntest: hello\n \ntest)
33
+ headers, body = parse(response)
34
+ assert_equal({"server" => "autoresponder", "test" => "hello"}, headers)
35
+ assert_equal "test", body
36
+ end
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auto_response
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - qhwa,,,
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: qhwa@163.com
16
+ executables:
17
+ - ar
18
+ - start_ar.rb
19
+ extensions: []
20
+ extra_rdoc_files:
21
+ - readme.md
22
+ files:
23
+ - readme.md
24
+ - rules.sample
25
+ - Gemfile
26
+ - Gemfile.lock
27
+ - bin/start_ar.rb
28
+ - bin/ar
29
+ - test/all-test.rb
30
+ - test/response_text_parser_test.rb
31
+ - test/respond_with_number_test.rb
32
+ - test/respond_with_url_test.rb
33
+ - test/respond_with_string_test.rb
34
+ - test/respond_with_array_test.rb
35
+ - test/fixture/passwd
36
+ - test/fixture/hello_world.txt
37
+ - test/respond_with_file_test.rb
38
+ - test/helper.rb
39
+ - test/match_with_reg_test.rb
40
+ - lib/autoresponse.rb
41
+ - lib/ar/parser.rb
42
+ - lib/ar/proxyserver.rb
43
+ - lib/ar/rule_manager.rb
44
+ - lib/ar/rule_dsl.rb
45
+ homepage: http://yoursite.example.com
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --main
50
+ - readme.md
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.24
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: What this thing does
71
+ test_files: []