waithook 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/bin/waithook +46 -0
- data/lib/waithook/cli.rb +64 -0
- data/lib/waithook/logger_with_trace.rb +49 -0
- data/lib/waithook/version.rb +1 -1
- data/lib/waithook/websocket_client.rb +30 -14
- data/lib/waithook.rb +95 -52
- data/tests/waithook_test.rb +43 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d3624c5bebd573d8f2e33f66d96d19b93acc3a9
|
4
|
+
data.tar.gz: 25d37ca7b8c923b24c04425ce35f75ed997d9033
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32a2181e21aa618a589c64d7dbd07132ebdc1942c4169bfe26019b8061d05ea18a494d0ffb8e2da343accba7307427c9c69742ed3a05477897ff3d91dd3de847
|
7
|
+
data.tar.gz: 3a96f332074cbd7a5e8364bcebbc42de580ca8575f39ad17c19c28d0f012320c09cd36e7df2d18ad664bd43a3852a682ad79bb608fd3ca7796fb4cf090f930b3
|
data/Gemfile.lock
CHANGED
data/bin/waithook
CHANGED
@@ -2,3 +2,49 @@
|
|
2
2
|
|
3
3
|
$:.push(File.expand_path("../../lib", __FILE__))
|
4
4
|
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
def help_message
|
8
|
+
[
|
9
|
+
"Waithook command line client.",
|
10
|
+
"",
|
11
|
+
"Example usage:",
|
12
|
+
" waithook waithook.herokuapp.com/my_path",
|
13
|
+
" waithook waithook.herokuapp.com/my_path --forward http://localhost:3000/notify"
|
14
|
+
].join("\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
options = {}
|
18
|
+
|
19
|
+
begin
|
20
|
+
OptionParser.new do |opts|
|
21
|
+
opts.banner = help_message + "\nOptions:"
|
22
|
+
|
23
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
24
|
+
options[:verbose] = v
|
25
|
+
end
|
26
|
+
opts.on("-f URL", "--forward URL", "Forward to HTTP server") do |value|
|
27
|
+
options[:forward] = value
|
28
|
+
end
|
29
|
+
end.parse!
|
30
|
+
rescue OptionParser::InvalidOption => error
|
31
|
+
require 'waithook'
|
32
|
+
puts Waithook::WithColor.red(error.message)
|
33
|
+
puts "Please use --help to list of arguments"
|
34
|
+
exit 1
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'waithook'
|
39
|
+
if ARGV.first
|
40
|
+
Waithook::CLI.listen(ARGV.first, options)
|
41
|
+
else
|
42
|
+
puts Waithook::WithColor.red("URL is required\n")
|
43
|
+
puts help_message
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
rescue Waithook::CLI::ArgError => error
|
47
|
+
puts Waithook::WithColor.red(error.message)
|
48
|
+
puts help_message
|
49
|
+
exit 1
|
50
|
+
end
|
data/lib/waithook/cli.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
class Waithook
|
2
|
+
module WithColor
|
3
|
+
extend self
|
4
|
+
def black(s); "\033[30m#{s}\033[0m" end
|
5
|
+
def red(s); "\033[31m#{s}\033[0m" end
|
6
|
+
def green(s); "\033[32m#{s}\033[0m" end
|
7
|
+
def brown(s); "\033[33m#{s}\033[0m" end
|
8
|
+
def blue(s); "\033[34m#{s}\033[0m" end
|
9
|
+
def magenta(s); "\033[35m#{s}\033[0m" end
|
10
|
+
def cyan(s); "\033[36m#{s}\033[0m" end
|
11
|
+
def gray(s); "\033[37m#{s}\033[0m" end
|
12
|
+
def yellow(s); "\033[93m#{s}\033[0m" end
|
13
|
+
def bold(s); "\e[1m#{s}\e[m" end
|
14
|
+
end
|
15
|
+
|
16
|
+
module CLI
|
17
|
+
class ArgError < ArgumentError; end
|
18
|
+
|
19
|
+
extend self
|
20
|
+
|
21
|
+
def listen(url, options)
|
22
|
+
puts "Run with options: #{options}" if options[:verbose]
|
23
|
+
unless url.start_with?('ws://', 'wss://')
|
24
|
+
url = 'wss://' + url
|
25
|
+
end
|
26
|
+
|
27
|
+
unless url =~ /\A#{URI::regexp(['ws', 'wss'])}\z/
|
28
|
+
raise ArgError, "#{url.inspect} is not a valid websocket URL"
|
29
|
+
end
|
30
|
+
|
31
|
+
uri = URI.parse(url)
|
32
|
+
port = uri.scheme == 'wss' ? 443 : uri.port
|
33
|
+
path = uri.path.start_with?('/') ? uri.path.sub(/^\//, '') : uri.path
|
34
|
+
logger_level = options[:verbose] ? 'trace' : 'warn'
|
35
|
+
|
36
|
+
puts WithColor.green("Connecting to #{url}")
|
37
|
+
waithook = Waithook.new(host: uri.host, port: port, path: path, logger_level: logger_level)
|
38
|
+
puts WithColor.green("Connected! Waiting to for message...") if waithook.client.wait_connected
|
39
|
+
|
40
|
+
while true
|
41
|
+
message = waithook.wait_message
|
42
|
+
puts message.message
|
43
|
+
if options[:forward]
|
44
|
+
Thread.new do
|
45
|
+
begin
|
46
|
+
forward_url = if options[:forward].start_with?('http://', 'https://')
|
47
|
+
forward_url
|
48
|
+
else
|
49
|
+
"http://#{options[:forward]}"
|
50
|
+
end
|
51
|
+
|
52
|
+
puts WithColor.brown("Sending as HTTP to #{forward_url}")
|
53
|
+
response = message.send_to(forward_url)
|
54
|
+
puts WithColor.brown("Reponse from #{forward_url} -> #{WithColor.bold("#{response.code} #{response.message}")}")
|
55
|
+
rescue => error
|
56
|
+
puts WithColor.red("#{error.message} (#{error.class})")
|
57
|
+
puts WithColor.red(error.backtrace.join("\n"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
# Just add trace level
|
4
|
+
class LoggerWithTrace < ::Logger
|
5
|
+
module Severity
|
6
|
+
include ::Logger::Severity
|
7
|
+
TRACE = -1
|
8
|
+
end
|
9
|
+
|
10
|
+
TRACE = Severity::TRACE
|
11
|
+
|
12
|
+
def trace(progname = nil, &block)
|
13
|
+
add(TRACE, nil, progname, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def trace?
|
17
|
+
@level <= TRACE
|
18
|
+
end
|
19
|
+
|
20
|
+
def level=(severity)
|
21
|
+
if severity.is_a?(Integer)
|
22
|
+
@level = severity
|
23
|
+
else
|
24
|
+
@level = case severity.to_s.downcase
|
25
|
+
when 'trace'.freeze then TRACE
|
26
|
+
when 'debug'.freeze then DEBUG
|
27
|
+
when 'info'.freeze then INFO
|
28
|
+
when 'warn'.freeze then WARN
|
29
|
+
when 'error'.freeze then ERROR
|
30
|
+
when 'fatal'.freeze then FATAL
|
31
|
+
when 'unknown'.freeze then UNKNOWN
|
32
|
+
else
|
33
|
+
raise ArgumentError, "invalid log level: #{severity}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup(options)
|
39
|
+
self.progname = options[:progname]
|
40
|
+
self.formatter = proc do |serverity, time, progname, msg|
|
41
|
+
msg.lines.map do |line|
|
42
|
+
"#{progname} :: #{line}"
|
43
|
+
end.join("") + "\n"
|
44
|
+
end
|
45
|
+
self.level = options[:level]
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
data/lib/waithook/version.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'socket'
|
2
|
-
require 'logger'
|
3
2
|
require 'websocket'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
require_relative 'logger_with_trace'
|
4
6
|
|
5
7
|
class Waithook
|
6
8
|
class WebsocketClient
|
@@ -29,26 +31,24 @@ class Waithook
|
|
29
31
|
@options = options
|
30
32
|
|
31
33
|
@waiters = []
|
34
|
+
@connect_waiters = []
|
32
35
|
@handshake_received = false
|
33
36
|
@messages = Queue.new
|
34
37
|
@is_open = false
|
35
38
|
|
36
|
-
@output = options[:output] ||
|
39
|
+
@output = options[:output] || $stdout
|
37
40
|
|
38
41
|
if options[:logger] === false
|
39
42
|
@output = StringIO.new
|
40
43
|
end
|
41
44
|
|
42
|
-
if options[:logger]
|
45
|
+
if options[:logger] && options[:logger] != true
|
43
46
|
@logger = options[:logger]
|
44
47
|
else
|
45
|
-
@logger =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
"#{progname} :: #{line}"
|
50
|
-
end.join("") + "\n"
|
51
|
-
end
|
48
|
+
@logger = LoggerWithTrace.new(@output).setup(
|
49
|
+
progname: self.class.name,
|
50
|
+
level: options[:logger_level] || :info
|
51
|
+
)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -74,7 +74,7 @@ class Waithook
|
|
74
74
|
@is_open = true
|
75
75
|
@handshake = WebSocket::Handshake::Client.new(url: "ws://#{@host}/#{@path}")
|
76
76
|
|
77
|
-
logger.
|
77
|
+
logger.trace "Sending handshake:\n#{@handshake}"
|
78
78
|
|
79
79
|
@socket.print(@handshake)
|
80
80
|
_start_parser!
|
@@ -94,10 +94,10 @@ class Waithook
|
|
94
94
|
logger.debug "Start reading in thread"
|
95
95
|
handshake_response = _wait_handshake_response
|
96
96
|
@handshake << handshake_response
|
97
|
-
logger.
|
97
|
+
logger.trace "Handshake received:\n #{handshake_response}"
|
98
98
|
|
99
99
|
@frame_parser = WebSocket::Frame::Incoming::Client.new
|
100
|
-
|
100
|
+
_handshake_recieved!
|
101
101
|
_wait_frames!
|
102
102
|
rescue Object => error
|
103
103
|
logger.error "#{error.class}: #{error.message}\n#{error.backtrace.join("\n")}"
|
@@ -135,6 +135,20 @@ class Waithook
|
|
135
135
|
@messages.pop
|
136
136
|
end
|
137
137
|
|
138
|
+
def wait_connected
|
139
|
+
return true if @handshake_received
|
140
|
+
waiter = Waiter.new
|
141
|
+
@connect_waiters << waiter
|
142
|
+
waiter.wait
|
143
|
+
end
|
144
|
+
|
145
|
+
def _handshake_recieved!
|
146
|
+
@handshake_received = true
|
147
|
+
while waiter = @connect_waiters.shift
|
148
|
+
waiter.notify(true)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
138
152
|
def _notify_waiters(type, payload)
|
139
153
|
while waiter = @waiters.shift
|
140
154
|
waiter.notify([type, payload])
|
@@ -144,11 +158,13 @@ class Waithook
|
|
144
158
|
def _send_frame(type, payload = nil)
|
145
159
|
wait_handshake!
|
146
160
|
frame = WebSocket::Frame::Outgoing::Client.new(version: @handshake.version, data: payload, type: type)
|
147
|
-
logger.
|
161
|
+
logger.trace "Sending :#{frame.type} #{payload ? "DATA: #{frame.data}" : "(no data)"}"
|
148
162
|
@socket.write(frame.to_s)
|
149
163
|
end
|
150
164
|
|
151
165
|
def _process_frame(message)
|
166
|
+
logger.trace "Received :#{message.type} #{message.data ? "DATA: #{message.data}" : "(no data)"}"
|
167
|
+
|
152
168
|
if message.type == :ping
|
153
169
|
send_pong!
|
154
170
|
end
|
data/lib/waithook.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'timeout'
|
2
4
|
require 'json'
|
5
|
+
require 'stringio'
|
3
6
|
|
7
|
+
require_relative 'waithook/logger_with_trace'
|
4
8
|
require_relative 'waithook/websocket_client'
|
9
|
+
require_relative 'waithook/cli'
|
5
10
|
|
6
11
|
class Waithook
|
7
12
|
|
8
13
|
SERVER_HOST = "waithook.herokuapp.com"
|
9
14
|
SERVER_PORT = 443
|
10
15
|
|
11
|
-
def self.subscribe(
|
12
|
-
instance = new(
|
16
|
+
def self.subscribe(options = {}, &block)
|
17
|
+
instance = new(options)
|
13
18
|
if block
|
14
19
|
instance.filter = block
|
15
20
|
end
|
@@ -17,30 +22,52 @@ class Waithook
|
|
17
22
|
instance
|
18
23
|
end
|
19
24
|
|
25
|
+
def self.default_path
|
26
|
+
@default_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.default_path=(value)
|
30
|
+
@default_path = value
|
31
|
+
end
|
32
|
+
|
20
33
|
attr_accessor :filter
|
21
34
|
attr_accessor :messages
|
22
35
|
attr_reader :client
|
36
|
+
attr_reader :options
|
23
37
|
|
24
|
-
def initialize(
|
25
|
-
options = {
|
38
|
+
def initialize(options = {})
|
39
|
+
@options = {
|
26
40
|
host: SERVER_HOST,
|
27
41
|
port: SERVER_PORT,
|
28
|
-
auto_connect: true
|
42
|
+
auto_connect: true,
|
43
|
+
path: self.class.default_path
|
29
44
|
}.merge(options)
|
30
45
|
|
31
|
-
@path
|
46
|
+
if @options[:path] == nil
|
47
|
+
raise ArgumentError, ":path is missing. Please add :path to options argument or set Waithook.default_path = 'foo'"
|
48
|
+
end
|
49
|
+
|
32
50
|
@client = WebsocketClient.new(
|
33
|
-
path: path,
|
34
|
-
host: options[:host],
|
35
|
-
port: options[:port],
|
36
|
-
logger: options[:logger]
|
51
|
+
path: @options[:path],
|
52
|
+
host: @options[:host],
|
53
|
+
port: @options[:port],
|
54
|
+
logger: @options[:logger],
|
55
|
+
logger_level: @options[:logger_level],
|
56
|
+
output: @options[:output]
|
37
57
|
)
|
38
58
|
|
39
59
|
@messages = []
|
40
60
|
@filter = nil
|
41
61
|
@started = false
|
42
62
|
|
43
|
-
connect! if options[:auto_connect]
|
63
|
+
connect! if @options[:auto_connect]
|
64
|
+
end
|
65
|
+
|
66
|
+
def logger
|
67
|
+
@logger ||= LoggerWithTrace.new(@options[:logger] ? $stdout : StringIO.new).setup(
|
68
|
+
progname: self.class.name,
|
69
|
+
level: @options[:logger_level] || :info
|
70
|
+
)
|
44
71
|
end
|
45
72
|
|
46
73
|
def connect!
|
@@ -54,50 +81,31 @@ class Waithook
|
|
54
81
|
!!@started
|
55
82
|
end
|
56
83
|
|
57
|
-
def forward_to(url)
|
58
|
-
webhook = wait_message
|
59
|
-
|
60
|
-
uri = URI.parse(url)
|
61
|
-
response = nil
|
62
|
-
|
63
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
64
|
-
http_klass = case webhook.method
|
65
|
-
when "GET" then Net::HTTP::Get
|
66
|
-
when "POST" then Net::HTTP::Post
|
67
|
-
when "PUT" then Net::HTTP::Put
|
68
|
-
when "PATCH" then Net::HTTP::Patch
|
69
|
-
when "HEAD" then Net::HTTP::Head
|
70
|
-
when "DELETE" then Net::HTTP::Delete
|
71
|
-
when "MOVE" then Net::HTTP::Move
|
72
|
-
when "COPY" then Net::HTTP::Copy
|
73
|
-
when "HEAD" then Net::HTTP::Head
|
74
|
-
else Net::HTTP::Post
|
75
|
-
end
|
76
|
-
|
77
|
-
request = http_klass.new(uri)
|
78
|
-
webhook.headers.each do |key, value|
|
79
|
-
request[key] = value
|
80
|
-
end
|
81
|
-
|
82
|
-
if webhook.body
|
83
|
-
request.body = webhook.body
|
84
|
-
end
|
85
|
-
|
86
|
-
response = http.request(request)
|
87
|
-
end
|
88
|
-
|
89
|
-
response
|
84
|
+
def forward_to(url, options = {})
|
85
|
+
webhook = wait_message(options)
|
86
|
+
webhook.send_to(url) unless webhook.nil?
|
90
87
|
end
|
91
88
|
|
92
|
-
def wait_message
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
89
|
+
def wait_message(options = {})
|
90
|
+
raise_timeout_error = options.has_key?(:raise_on_timeout) ? options[:raise_on_timeout] : true
|
91
|
+
timeout = options[:timeout] || @options[:timeout] || 0
|
92
|
+
|
93
|
+
start_time = Time.new.to_f
|
94
|
+
Timeout.timeout(timeout) do
|
95
|
+
while true
|
96
|
+
type, data = @client.wait_message
|
97
|
+
webhook = Webhook.new(data)
|
98
|
+
if @filter && @filter.call(webhook) || !@filter
|
99
|
+
@messages << webhook
|
100
|
+
return webhook
|
101
|
+
end
|
99
102
|
end
|
100
103
|
end
|
104
|
+
rescue Timeout::Error => error
|
105
|
+
time_diff = (Time.now.to_f - start_time).round(3)
|
106
|
+
logger.error "#{error.class}: #{error.message} (after #{time_diff} seconds)"
|
107
|
+
raise error if raise_timeout_error
|
108
|
+
return nil
|
101
109
|
end
|
102
110
|
|
103
111
|
def close!
|
@@ -110,9 +118,11 @@ class Waithook
|
|
110
118
|
attr_reader :headers
|
111
119
|
attr_reader :body
|
112
120
|
attr_reader :method
|
121
|
+
attr_reader :message
|
113
122
|
|
114
123
|
def initialize(payload)
|
115
|
-
|
124
|
+
@message = payload
|
125
|
+
data = JSON.parse(@message)
|
116
126
|
@url = data['url']
|
117
127
|
@headers = data['headers']
|
118
128
|
@body = data['body']
|
@@ -124,5 +134,38 @@ class Waithook
|
|
124
134
|
@json_body ||= JSON.parse(@body)
|
125
135
|
end
|
126
136
|
end
|
137
|
+
|
138
|
+
def send_to(url)
|
139
|
+
uri = URI.parse(url)
|
140
|
+
response = nil
|
141
|
+
|
142
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
143
|
+
http_klass = case method
|
144
|
+
when "GET" then Net::HTTP::Get
|
145
|
+
when "POST" then Net::HTTP::Post
|
146
|
+
when "PUT" then Net::HTTP::Put
|
147
|
+
when "PATCH" then Net::HTTP::Patch
|
148
|
+
when "HEAD" then Net::HTTP::Head
|
149
|
+
when "DELETE" then Net::HTTP::Delete
|
150
|
+
when "MOVE" then Net::HTTP::Move
|
151
|
+
when "COPY" then Net::HTTP::Copy
|
152
|
+
when "HEAD" then Net::HTTP::Head
|
153
|
+
else Net::HTTP::Post
|
154
|
+
end
|
155
|
+
|
156
|
+
request = http_klass.new(uri)
|
157
|
+
headers.each do |key, value|
|
158
|
+
request[key] = value
|
159
|
+
end
|
160
|
+
|
161
|
+
if body
|
162
|
+
request.body = body
|
163
|
+
end
|
164
|
+
|
165
|
+
response = http.request(request)
|
166
|
+
end
|
167
|
+
|
168
|
+
response
|
169
|
+
end
|
127
170
|
end
|
128
171
|
end
|
data/tests/waithook_test.rb
CHANGED
@@ -11,7 +11,7 @@ describe "Waithook" do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def default_client(options = {})
|
14
|
-
client = Waithook.subscribe(
|
14
|
+
client = Waithook.subscribe({path: 'my-super-test', host: HOST, port: PORT, logger: false}.merge(options))
|
15
15
|
@waithook_instances.push(client)
|
16
16
|
client
|
17
17
|
end
|
@@ -54,4 +54,46 @@ describe "Waithook" do
|
|
54
54
|
assert_equal(message, webhook.json_body)
|
55
55
|
assert_equal("POST", webhook.method)
|
56
56
|
end
|
57
|
+
|
58
|
+
it "should have trace log level" do
|
59
|
+
out, err = capture_io do
|
60
|
+
default_client(logger_level: :trace, logger: true)
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_includes(out, 'Sec-WebSocket-Version')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should be more quiet generally" do
|
67
|
+
out, err = capture_io do
|
68
|
+
default_client(logger: true)
|
69
|
+
end
|
70
|
+
|
71
|
+
refute_includes(out, 'Sec-WebSocket-Version')
|
72
|
+
end
|
73
|
+
|
74
|
+
it "wait_message should raise exception after timeout" do
|
75
|
+
assert_raises(Timeout::Error) do
|
76
|
+
default_client.wait_message(timeout: 0.1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "wait_message should return nil after timeout" do
|
81
|
+
waithook = default_client
|
82
|
+
assert_equal(nil, waithook.wait_message(timeout: 0.1, raise_on_timeout: false))
|
83
|
+
end
|
84
|
+
|
85
|
+
it "forward_to should raise exception after timeout" do
|
86
|
+
assert_raises(Timeout::Error) do
|
87
|
+
default_client.forward_to('', timeout: 0.1)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "forward_to should return nil after timeout" do
|
92
|
+
out, err = capture_io do
|
93
|
+
waithook = default_client(logger: true)
|
94
|
+
assert_equal(nil, waithook.forward_to('', timeout: 0.1, raise_on_timeout: false))
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_includes(out, "Timeout::Error: execution expired")
|
98
|
+
end
|
57
99
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: waithook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Evstigneev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: websocket
|
@@ -42,6 +42,8 @@ files:
|
|
42
42
|
- example/real_server_test.rb
|
43
43
|
- example/waithook_example.rb
|
44
44
|
- lib/waithook.rb
|
45
|
+
- lib/waithook/cli.rb
|
46
|
+
- lib/waithook/logger_with_trace.rb
|
45
47
|
- lib/waithook/version.rb
|
46
48
|
- lib/waithook/websocket_client.rb
|
47
49
|
- tests/server_test.rb
|