yup 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,11 +2,15 @@ source "http://rubygems.org"
2
2
 
3
3
  gem "eventmachine"
4
4
  gem "em-http-request"
5
+ gem "http_request.rb"
5
6
  gem "http_parser.rb"
7
+ gem "tuple"
8
+ gem "dk-bdb"
9
+ gem "yajl-ruby"
6
10
 
7
11
  group :development do
8
- gem "shoulda", ">= 0"
9
12
  gem "yard", "~> 0.6.0"
13
+ gem "minitest", ">= 0"
10
14
  gem "bundler", "~> 1.0.0"
11
15
  gem "jeweler", "~> 1.5.2"
12
16
  gem "rcov", ">= 0"
data/Gemfile.lock CHANGED
@@ -2,6 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  addressable (2.2.6)
5
+ dk-bdb (0.2.4.2)
5
6
  em-http-request (0.3.0)
6
7
  addressable (>= 2.0.0)
7
8
  escape_utils
@@ -10,13 +11,16 @@ GEM
10
11
  eventmachine (0.12.10)
11
12
  git (1.2.5)
12
13
  http_parser.rb (0.5.1)
14
+ http_request.rb (1.1.11)
13
15
  jeweler (1.5.2)
14
16
  bundler (~> 1.0.0)
15
17
  git (>= 1.2.5)
16
18
  rake
19
+ minitest (2.5.0)
17
20
  rake (0.9.2)
18
21
  rcov (0.9.10)
19
- shoulda (2.11.3)
22
+ tuple (0.1.2)
23
+ yajl-ruby (0.8.3)
20
24
  yard (0.6.8)
21
25
 
22
26
  PLATFORMS
@@ -24,10 +28,14 @@ PLATFORMS
24
28
 
25
29
  DEPENDENCIES
26
30
  bundler (~> 1.0.0)
31
+ dk-bdb
27
32
  em-http-request
28
33
  eventmachine
29
34
  http_parser.rb
35
+ http_request.rb
30
36
  jeweler (~> 1.5.2)
37
+ minitest
31
38
  rcov
32
- shoulda
39
+ tuple
40
+ yajl-ruby
33
41
  yard (~> 0.6.0)
data/README.rdoc CHANGED
@@ -4,10 +4,16 @@ This is the small daemon for transparent asynchronous delegating HTTP requests w
4
4
 
5
5
  When a http request is arrived the yup daemon (yupd) answers to the client configured answer (by default 200 OK). Then the yupd forwards the http request to the specified host and retries if a timeout error was happend.
6
6
 
7
+ == Non-persistent queue
8
+ By default, nonpersistent queue is used. A limit (the option --watermark) at which new requests will be dropped.
9
+
10
+ == Persistent queue
11
+ If you want use persistent queue you need to specify the option --persistent with a path to a database.
12
+
7
13
  == One of use cases
8
14
 
9
15
  For example we can have a rails app which send exceptions to an errbit by the gem hoptoad_notifier. We know the errbit can be not available by network issues or some else reasons, but we do not want lose exceptions. To resolve this problem we can start yupd on the same host with the rails app:
10
- yupd --listen localhost:8081 --status-code 201 errbit.host.somewhere
16
+ yupd --listen localhost:8081 --status-code 201 --persistent /var/db/yupd-errbit errbit.host.somewhere
11
17
 
12
18
  Reconfiguration of hoptoad_notifier is very ease:
13
19
  HoptoadNotifier.configure do |config|
@@ -20,9 +26,9 @@ Now problem of availability of errbit is assigned to the yupd.
20
26
 
21
27
  == Roadmap to 0.1
22
28
 
29
+ * More better documentation
23
30
  * Daemonize
24
31
  * Preforking
25
- * Persistent HTTP requests queue
26
32
  * A configurable map of different delegating rules
27
33
  * Tests...
28
34
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/bin/yupd CHANGED
@@ -18,6 +18,7 @@ Options:
18
18
  --watermark <number> Maximum of concurrent requests (default 100)
19
19
  --loglevel <level> Logging severity (default fatal).
20
20
  Available log levels: fatal, error, warn, info, debug.
21
+ --persistent <path> Use persistent queue.
21
22
 
22
23
  Examples:
23
24
  yupd --listen 0.0.0.0:8081 --status-code 201 errbit.host.somewhere
@@ -39,6 +40,7 @@ opts = GetoptLong.new(*[['--help', '-h', GetoptLong::NO_ARGUMENT],
39
40
  ['--resend-delay', '-d', GetoptLong::REQUIRED_ARGUMENT],
40
41
  ['--watermark', GetoptLong::REQUIRED_ARGUMENT],
41
42
  ['--loglevel', GetoptLong::REQUIRED_ARGUMENT],
43
+ ['--persistent', GetoptLong::REQUIRED_ARGUMENT],
42
44
  ])
43
45
  config = {:loglevel => LEVELS["fatal"]}
44
46
 
@@ -63,6 +65,8 @@ opts.each do |opt, arg|
63
65
  usage
64
66
  exit 1
65
67
  end
68
+ when '--persistent'
69
+ config[:persistent] = arg || "/tmp/queue"
66
70
  end
67
71
  end
68
72
 
@@ -77,4 +81,10 @@ config[:forward_to] = ARGV.shift
77
81
  Yup.logger.level = config[:loglevel]
78
82
  Yup.watermark = config[:watermark] if config.has_key?(:watermark)
79
83
  Yup.resend_delay = config[:resend_delay] if config.has_key?(:resend_delay)
80
- Yup.run(config)
84
+
85
+ if config.has_key?(:persistent)
86
+ # Yup::State.repair_if_need(config[:persistent])
87
+ Yup.run_with_state(config)
88
+ else
89
+ Yup.run(config)
90
+ end
data/lib/yup.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'eventmachine'
3
3
  require 'logger'
4
+ require 'yajl'
5
+ require 'tmpdir'
4
6
 
5
7
  require 'yup/request_forwarder'
6
8
  require 'yup/request_handler'
9
+ require 'yup/state'
7
10
 
8
11
  module Yup
9
12
  @@resend_delay = 5.0
@@ -24,10 +27,42 @@ module Yup
24
27
  status_code = config[:status_code] || 200
25
28
  forward_to = config[:forward_to]
26
29
 
27
- EventMachine::run do
28
- EventMachine::start_server(host, port, RequestHandler,
29
- forward_to, status_code)
30
+ EventMachine.run do
31
+ EventMachine.start_server(host, port, RequestHandler, forward_to, status_code, nil)
30
32
  logger.info { "listening on #{host}:#{port}" }
31
33
  end
32
34
  end
35
+
36
+ def self.run_with_state(config)
37
+ host = config[:listen_host] || 'localhost'
38
+ port = config[:listen_port] || 8080
39
+ status_code = config[:status_code] || 200
40
+ forward_to = config[:forward_to]
41
+ dbpath = config[:persistent]
42
+ feedback_channel = File.join(Dir.tmpdir, "yupd-#{$$}-feedback")
43
+ state = Yup::State.new(dbpath, forward_to, feedback_channel)
44
+
45
+ pid = Process.fork do
46
+ State::RequestForwarder.new(state, forward_to).run_loop
47
+ end
48
+
49
+ if pid
50
+ db_closer = proc do
51
+ Yup.logger.info { "Terminating consumer #{$$}" }
52
+ Process.kill("KILL", pid)
53
+ state.close
54
+ exit 0
55
+ end
56
+ Signal.trap("TERM", &db_closer)
57
+ Signal.trap("INT", &db_closer)
58
+ end
59
+
60
+ EventMachine.run do
61
+ EventMachine.start_server(host, port, RequestHandler, forward_to, status_code, state)
62
+ logger.info { "Listening on #{host}:#{port}" }
63
+
64
+ EventMachine.start_unix_domain_server(feedback_channel, State::FeedbackHandler, state)
65
+ logger.info { "Feedback through #{feedback_channel}" }
66
+ end
67
+ end
33
68
  end
@@ -1,22 +1,25 @@
1
1
  require 'em-http-request'
2
+ require 'http_request'
2
3
 
3
4
  module Yup
4
5
  class RequestForwarder
5
- def initialize(parser, body, forward_to)
6
- @parser = parser
7
- @body = body
8
- @forward_to = forward_to
6
+ def initialize(http_method, request_url, headers, body, forward_to)
7
+ @http_method = http_method
8
+ @request_url = request_url
9
+ @headers = headers
10
+ @body = body
11
+ @forward_to = forward_to
9
12
 
10
13
  @logger = Yup.logger
11
14
  end
12
15
 
13
16
  def run
14
- http_method = @parser.http_method.downcase.to_sym
15
- http_url = "http://#{@forward_to}#{@parser.request_url}"
17
+ http_method = @http_method.to_sym
18
+ http_url = "http://#{@forward_to}#{@request_url}"
16
19
  http = EventMachine::HttpRequest.
17
20
  new(http_url).
18
21
  send(http_method,
19
- :head => @parser.headers.merge('Host' => @forward_to),
22
+ :head => @headers.merge('Host' => @forward_to),
20
23
  :body => @body)
21
24
 
22
25
  http.callback do
@@ -35,9 +38,88 @@ module Yup
35
38
  http.errback do
36
39
  @logger.info '--- ERROR'
37
40
  @logger.debug { http.inspect }
41
+ @logger.debug { http.response_header.inspect }
42
+ @logger.debug { http.response.inspect }
38
43
 
39
44
  EventMachine.add_timer(Yup.resend_delay) { self.run }
40
45
  end
41
46
  end
42
47
  end
48
+
49
+ class State
50
+ class RequestForwarder
51
+ def initialize(state, forward_to)
52
+ @state = state
53
+ @forward_to = forward_to
54
+
55
+ @logger = Yup.logger
56
+ @yajl = Yajl::Parser.new(:symbolize_keys => true)
57
+ @yajl.on_parse_complete = method(:make_request)
58
+ end
59
+
60
+ def run_loop
61
+ loop do
62
+ data = @state.bpop
63
+ begin
64
+ @yajl << data
65
+ rescue Yajl::ParseError
66
+ @logger.error { "Error while parsing \"#{data}\"" }
67
+ end
68
+ end
69
+ end
70
+
71
+ def make_request(req)
72
+ begin
73
+ http_method, request_url, headers, body = req
74
+ headers = Hash[headers.to_a.flatten.map(&:to_s)]
75
+
76
+ http_method = http_method.to_sym
77
+ http_url = "http://#{@forward_to}#{request_url}"
78
+ http = HttpRequest.
79
+ send(http_method,
80
+ :url => http_url,
81
+ :headers => headers.merge('Host' => @forward_to),
82
+ :parameters => body)
83
+
84
+ if http.code_2xx?
85
+ @logger.info '--- SUCCESS'
86
+ else
87
+ @logger.info '--- FAIL'
88
+ @logger.debug { http.inspect }
89
+ @logger.debug { http.response_header.inspect }
90
+ @logger.debug { http.response.inspect }
91
+ end
92
+ rescue Exception => e
93
+ @logger.info '--- ERROR'
94
+ @logger.debug { e }
95
+
96
+ @state.to_feedback(Yajl::Encoder.encode([http_method.downcase, request_url, headers, body]))
97
+
98
+ sleep Yup.resend_delay
99
+ end
100
+ end
101
+ end
102
+
103
+ class FeedbackHandler < EM::Connection
104
+ def initialize(state)
105
+ @state = state
106
+
107
+ @logger = Yup.logger
108
+ @yajl = Yajl::Parser.new(:symbolize_keys => true)
109
+ @yajl.on_parse_complete = method(:on_message)
110
+ end
111
+
112
+ def receive_data(data)
113
+ begin
114
+ @yajl << data
115
+ rescue Yajl::ParseError
116
+ @logger.error { "Error while parsing \"#{data}\"" }
117
+ end
118
+ end
119
+
120
+ def on_message(req)
121
+ @state.push(Yajl::Encoder.encode(req))
122
+ end
123
+ end
124
+ end
43
125
  end
@@ -5,9 +5,10 @@ module Yup
5
5
  class RequestHandler < EM::Connection
6
6
  attr_reader :queue
7
7
 
8
- def initialize(forward_to, status_code)
8
+ def initialize(forward_to, status_code, state)
9
9
  @forward_to = forward_to
10
10
  @status_code = status_code
11
+ @state = state
11
12
 
12
13
  @logger = Yup.logger
13
14
  @chunks = []
@@ -31,24 +32,37 @@ module Yup
31
32
 
32
33
  def on_message_complete
33
34
  @logger.info "-- got request"
34
- @logger.info { "HTTP version : " + @parser.http_version.join('.') }
35
- @logger.info { "HTTP method : " + @parser.http_method }
35
+ @logger.info { "HTTP version : " + @parser.http_version.join('.') }
36
+ @logger.info { "HTTP method : " + @parser.http_method }
36
37
  @logger.info { "HTTP request_url : " + @parser.request_url }
37
- @logger.debug { "HTTP headers : " + @parser.headers.inspect }
38
+ @logger.debug { "HTTP headers : " + @parser.headers.inspect }
39
+ @logger.debug { "HTTP body : " + @body }
38
40
 
41
+ send_answer
42
+ shedule_request
43
+ end
44
+
45
+ private
46
+ def send_answer
39
47
  resp = WEBrick::HTTPResponse.new(:HTTPVersion => '1.1')
40
48
  resp.status = @status_code
41
49
  resp['Server'] = 'yupd'
42
50
  send_data resp.to_s
51
+ end
43
52
 
44
- unless Yup.watermark.zero?
45
- Yup.watermark -= 1
53
+ def shedule_request
54
+ if @state
55
+ @state.push(Yajl::Encoder.encode([@parser.http_method.downcase, @parser.request_url, @parser.headers, @body, @forward_to]))
56
+ else
57
+ unless Yup.watermark.zero?
58
+ Yup.watermark -= 1
46
59
 
47
- EventMachine.next_tick do
48
- RequestForwarder.new(@parser, @body, @forward_to).run
60
+ EventMachine.next_tick do
61
+ RequestForwarder.new(@parser.http_method.downcase, @parser.request_url, @parser.headers, @body, @forward_to).run
62
+ end
63
+ else
64
+ @logger.error "-- watermark is reached, drop"
49
65
  end
50
- else
51
- @logger.error "-- watermark is reached, drop"
52
66
  end
53
67
  end
54
68
  end
data/lib/yup/state.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'bdb'
2
+ require 'bdb/database'
3
+
4
+ module Yup
5
+ class State
6
+ RE_LEN = 1000
7
+
8
+ attr_reader :queue
9
+
10
+ def self.repair_if_need(path)
11
+ env = Bdb::Env.new(0)
12
+ env.open(path, Bdb::DB_CREATE | Bdb::DB_INIT_TXN | Bdb::DB_RECOVER, 0)
13
+ env.close()
14
+ end
15
+
16
+ def initialize(path, name, feedback_channel)
17
+ @path = path
18
+ @name = name
19
+ @feedback_channel = feedback_channel
20
+
21
+ @env = Bdb::Env.new(0)
22
+ @env = @env.open(@path, Bdb::DB_CREATE | Bdb::DB_INIT_MPOOL | Bdb::DB_INIT_CDB, 0)
23
+ @queue = @env.db
24
+ @queue.re_len = RE_LEN
25
+ @queue.open(nil, @name, nil, Bdb::Db::QUEUE, Bdb::DB_CREATE, 0)
26
+ end
27
+
28
+ def push(data)
29
+ Yup.logger.debug { "Pushing \"#{data}\"" }
30
+ i = 0
31
+ until (chunk = data.slice(i, RE_LEN)).nil?
32
+ @queue.put(nil, "", chunk, Bdb::DB_APPEND)
33
+ i += @queue.re_len
34
+ end
35
+ end
36
+
37
+ def bpop
38
+ data = @queue.get(nil, "", nil, Bdb::DB_CONSUME_WAIT)
39
+ Yup.logger.debug { "Bpoping \"#{data}\"" }
40
+ data
41
+ end
42
+
43
+ def to_feedback(data)
44
+ Yup.logger.debug { "Pushing to the feedback channel \"#{data}\"" }
45
+ sock = UNIXSocket.new(@feedback_channel)
46
+ sock.send(data, 0)
47
+ sock.close
48
+ end
49
+
50
+ def close
51
+ @queue.close(0)
52
+ end
53
+ end
54
+ end
data/test/helper.rb CHANGED
@@ -7,12 +7,13 @@ rescue Bundler::BundlerError => e
7
7
  $stderr.puts "Run `bundle install` to install missing gems"
8
8
  exit e.status_code
9
9
  end
10
- require 'test/unit'
11
- require 'shoulda'
10
+ require 'minitest/unit'
12
11
 
13
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
12
  $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
14
  require 'yup'
16
15
 
17
- class Test::Unit::TestCase
16
+ class MiniTest::Unit::TestCase
18
17
  end
18
+
19
+ MiniTest::Unit.autorun
data/test/test_yup.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  require 'helper'
2
2
 
3
- class TestYup < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
3
+ class TestYup < MiniTest::Unit::TestCase
4
+ def test_request_handler
5
+ flunk
6
+ end
7
+
8
+ def test_request_forwarder
9
+ flunk
6
10
  end
7
11
  end
data/yup.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{yup}
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Denis Sukhonin"]
12
- s.date = %q{2011-08-17}
12
+ s.date = %q{2011-09-07}
13
13
  s.default_executable = %q{yupd}
14
14
  s.description = %q{Just answers 200 (or specified) to a client and asynchronously forwards HTTP request to a configured host}
15
15
  s.email = %q{d.sukhonin@gmail.com}
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
30
30
  "lib/yup.rb",
31
31
  "lib/yup/request_forwarder.rb",
32
32
  "lib/yup/request_handler.rb",
33
+ "lib/yup/state.rb",
33
34
  "test/helper.rb",
34
35
  "test/test_yup.rb",
35
36
  "yup.gemspec"
@@ -51,18 +52,26 @@ Gem::Specification.new do |s|
51
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
53
  s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
53
54
  s.add_runtime_dependency(%q<em-http-request>, [">= 0"])
55
+ s.add_runtime_dependency(%q<http_request.rb>, [">= 0"])
54
56
  s.add_runtime_dependency(%q<http_parser.rb>, [">= 0"])
55
- s.add_development_dependency(%q<shoulda>, [">= 0"])
57
+ s.add_runtime_dependency(%q<tuple>, [">= 0"])
58
+ s.add_runtime_dependency(%q<dk-bdb>, [">= 0"])
59
+ s.add_runtime_dependency(%q<yajl-ruby>, [">= 0"])
56
60
  s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
61
+ s.add_development_dependency(%q<minitest>, [">= 0"])
57
62
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
58
63
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
59
64
  s.add_development_dependency(%q<rcov>, [">= 0"])
60
65
  else
61
66
  s.add_dependency(%q<eventmachine>, [">= 0"])
62
67
  s.add_dependency(%q<em-http-request>, [">= 0"])
68
+ s.add_dependency(%q<http_request.rb>, [">= 0"])
63
69
  s.add_dependency(%q<http_parser.rb>, [">= 0"])
64
- s.add_dependency(%q<shoulda>, [">= 0"])
70
+ s.add_dependency(%q<tuple>, [">= 0"])
71
+ s.add_dependency(%q<dk-bdb>, [">= 0"])
72
+ s.add_dependency(%q<yajl-ruby>, [">= 0"])
65
73
  s.add_dependency(%q<yard>, ["~> 0.6.0"])
74
+ s.add_dependency(%q<minitest>, [">= 0"])
66
75
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
76
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
68
77
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -70,9 +79,13 @@ Gem::Specification.new do |s|
70
79
  else
71
80
  s.add_dependency(%q<eventmachine>, [">= 0"])
72
81
  s.add_dependency(%q<em-http-request>, [">= 0"])
82
+ s.add_dependency(%q<http_request.rb>, [">= 0"])
73
83
  s.add_dependency(%q<http_parser.rb>, [">= 0"])
74
- s.add_dependency(%q<shoulda>, [">= 0"])
84
+ s.add_dependency(%q<tuple>, [">= 0"])
85
+ s.add_dependency(%q<dk-bdb>, [">= 0"])
86
+ s.add_dependency(%q<yajl-ruby>, [">= 0"])
75
87
  s.add_dependency(%q<yard>, ["~> 0.6.0"])
88
+ s.add_dependency(%q<minitest>, [">= 0"])
76
89
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
77
90
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
78
91
  s.add_dependency(%q<rcov>, [">= 0"])
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 3
9
- version: 0.0.3
8
+ - 4
9
+ version: 0.0.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Denis Sukhonin
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-08-17 00:00:00 +04:00
17
+ date: 2011-09-07 00:00:00 +04:00
18
18
  default_executable: yupd
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -44,7 +44,7 @@ dependencies:
44
44
  prerelease: false
45
45
  version_requirements: *id002
46
46
  - !ruby/object:Gem::Dependency
47
- name: http_parser.rb
47
+ name: http_request.rb
48
48
  requirement: &id003 !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
@@ -57,7 +57,7 @@ dependencies:
57
57
  prerelease: false
58
58
  version_requirements: *id003
59
59
  - !ruby/object:Gem::Dependency
60
- name: shoulda
60
+ name: http_parser.rb
61
61
  requirement: &id004 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
@@ -66,12 +66,51 @@ dependencies:
66
66
  segments:
67
67
  - 0
68
68
  version: "0"
69
- type: :development
69
+ type: :runtime
70
70
  prerelease: false
71
71
  version_requirements: *id004
72
72
  - !ruby/object:Gem::Dependency
73
- name: yard
73
+ name: tuple
74
74
  requirement: &id005 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: *id005
85
+ - !ruby/object:Gem::Dependency
86
+ name: dk-bdb
87
+ requirement: &id006 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ type: :runtime
96
+ prerelease: false
97
+ version_requirements: *id006
98
+ - !ruby/object:Gem::Dependency
99
+ name: yajl-ruby
100
+ requirement: &id007 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ type: :runtime
109
+ prerelease: false
110
+ version_requirements: *id007
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: &id008 !ruby/object:Gem::Requirement
75
114
  none: false
76
115
  requirements:
77
116
  - - ~>
@@ -83,10 +122,23 @@ dependencies:
83
122
  version: 0.6.0
84
123
  type: :development
85
124
  prerelease: false
86
- version_requirements: *id005
125
+ version_requirements: *id008
126
+ - !ruby/object:Gem::Dependency
127
+ name: minitest
128
+ requirement: &id009 !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: *id009
87
139
  - !ruby/object:Gem::Dependency
88
140
  name: bundler
89
- requirement: &id006 !ruby/object:Gem::Requirement
141
+ requirement: &id010 !ruby/object:Gem::Requirement
90
142
  none: false
91
143
  requirements:
92
144
  - - ~>
@@ -98,10 +150,10 @@ dependencies:
98
150
  version: 1.0.0
99
151
  type: :development
100
152
  prerelease: false
101
- version_requirements: *id006
153
+ version_requirements: *id010
102
154
  - !ruby/object:Gem::Dependency
103
155
  name: jeweler
104
- requirement: &id007 !ruby/object:Gem::Requirement
156
+ requirement: &id011 !ruby/object:Gem::Requirement
105
157
  none: false
106
158
  requirements:
107
159
  - - ~>
@@ -113,10 +165,10 @@ dependencies:
113
165
  version: 1.5.2
114
166
  type: :development
115
167
  prerelease: false
116
- version_requirements: *id007
168
+ version_requirements: *id011
117
169
  - !ruby/object:Gem::Dependency
118
170
  name: rcov
119
- requirement: &id008 !ruby/object:Gem::Requirement
171
+ requirement: &id012 !ruby/object:Gem::Requirement
120
172
  none: false
121
173
  requirements:
122
174
  - - ">="
@@ -126,7 +178,7 @@ dependencies:
126
178
  version: "0"
127
179
  type: :development
128
180
  prerelease: false
129
- version_requirements: *id008
181
+ version_requirements: *id012
130
182
  description: Just answers 200 (or specified) to a client and asynchronously forwards HTTP request to a configured host
131
183
  email: d.sukhonin@gmail.com
132
184
  executables:
@@ -148,6 +200,7 @@ files:
148
200
  - lib/yup.rb
149
201
  - lib/yup/request_forwarder.rb
150
202
  - lib/yup/request_handler.rb
203
+ - lib/yup/state.rb
151
204
  - test/helper.rb
152
205
  - test/test_yup.rb
153
206
  - yup.gemspec
@@ -165,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
165
218
  requirements:
166
219
  - - ">="
167
220
  - !ruby/object:Gem::Version
168
- hash: -3474122509911024601
221
+ hash: -4031501533023442341
169
222
  segments:
170
223
  - 0
171
224
  version: "0"