websockethook 0.1.0 → 0.1.01
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 +4 -4
- data/lib/websockethook.rb +70 -51
- data/spec/spec_helper.rb +4 -4
- data/spec/websockethook_spec.rb +70 -4
- metadata +29 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd91e0fc65cf4e459ff0657766ea34ac7a9f1d8e
|
4
|
+
data.tar.gz: 77ddfff2e872950d7621d7c58ac99ce9792f4e88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93056aaea58aac3939e1fe79d083d2f6eaf2fd465a234dcd50b748eb421a12484837c8b828ecd27d407b3ae3b68c16d0a28378ae91f0933adbae6990dd371105
|
7
|
+
data.tar.gz: 6de885962949b5db7165709a3dfcfe7aae3d89de67ddd869a3a8a058ca117f4abb0af15753db30559c0083a4ecafae6d29543837ea17cc3ace456367aa52caf4
|
data/lib/websockethook.rb
CHANGED
@@ -6,27 +6,18 @@ class WebSocketHook
|
|
6
6
|
DEFAULT_HOST = 'ws://web.sockethook.io'
|
7
7
|
|
8
8
|
def initialize(options = {})
|
9
|
-
@
|
10
|
-
@
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
raise 'Host (:host) must be a URL' unless @host.is_a?(String)
|
18
|
-
raise 'Pause (:pause) must be a float or integer' unless @pause.is_a?(Float) || @pause.is_a?(Integer)
|
19
|
-
raise 'Stay Alive (:stay_alive) must be a boolean (true/false)' unless @stay_alive == true || @stay_alive == false
|
20
|
-
raise 'Ping (:ping) must be an integer' unless @ping.is_a?(Integer)
|
21
|
-
raise 'Stopping (:stopping) must be boolean (true/false)' unless @stopping == true || @stopping == false
|
22
|
-
raise 'Hooks (:hooks) must be an array' unless hooks.is_a?(Array)
|
23
|
-
|
24
|
-
hooks.each {|hook| register(hook) }
|
9
|
+
@stopping = false
|
10
|
+
@hooks = []
|
11
|
+
initialize_host options
|
12
|
+
initialize_pause options
|
13
|
+
initialize_keep_alive options
|
14
|
+
initialize_ping options
|
15
|
+
initialize_hooks options
|
25
16
|
end
|
26
17
|
|
27
18
|
def register(id)
|
28
|
-
|
29
|
-
|
19
|
+
fail "Hook id '#{id}' must be a String" unless id.is_a?(String)
|
20
|
+
fail "Hook id must only be alphanumeric, '_', '.', or '_'" unless /^[a-zA-Z0-9\-_\.]*$/ === id
|
30
21
|
@hooks << id unless @hooks.include?(id)
|
31
22
|
end
|
32
23
|
|
@@ -35,13 +26,13 @@ class WebSocketHook
|
|
35
26
|
end
|
36
27
|
|
37
28
|
def listen(&block)
|
38
|
-
|
29
|
+
fail 'Block must be provided' unless block && block.is_a?(Proc)
|
39
30
|
begin
|
40
31
|
@stopping = false
|
41
32
|
listener(&block)
|
42
|
-
restart = @
|
33
|
+
restart = @keep_alive && !@stopping
|
43
34
|
if restart
|
44
|
-
block.call type:'restart', message:'restarting connection since it was lost'
|
35
|
+
block.call type: 'restart', message: 'restarting connection since it was lost'
|
45
36
|
sleep 5
|
46
37
|
end
|
47
38
|
end while restart
|
@@ -54,51 +45,79 @@ class WebSocketHook
|
|
54
45
|
|
55
46
|
private
|
56
47
|
|
48
|
+
def initialize_host(options = {})
|
49
|
+
@host = options[:host] || DEFAULT_HOST
|
50
|
+
fail 'Host (:host) must be a URL' unless @host.is_a?(String)
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize_pause(options = {})
|
54
|
+
@pause = options[:sleep] || 0.1
|
55
|
+
fail 'Pause (:pause) must be a float or integer' unless @pause.is_a?(Float) || @pause.is_a?(Integer)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize_keep_alive(options = {})
|
59
|
+
@keep_alive = options[:keep_alive] || true
|
60
|
+
fail 'Keep Alive (:keep_alive) must be a boolean (true/false)' unless @keep_alive == true || @keep_alive == false
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize_ping(options = {})
|
64
|
+
@ping = options[:ping] || 20
|
65
|
+
fail 'Ping (:ping) must be an integer' unless @ping.is_a?(Integer)
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize_hooks(options = {})
|
69
|
+
hooks = options[:hooks] || []
|
70
|
+
fail 'Hooks (:hooks) must be an array' unless hooks.is_a?(Array)
|
71
|
+
hooks.each { |hook| register(hook) }
|
72
|
+
end
|
73
|
+
|
57
74
|
def stop_em
|
58
|
-
|
59
|
-
|
60
|
-
rescue
|
61
|
-
end
|
75
|
+
EM.stop
|
76
|
+
rescue
|
62
77
|
end
|
63
78
|
|
64
79
|
def listener(&block)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
80
|
+
websocket(block) do |ws|
|
81
|
+
ws.on :open do
|
82
|
+
@hooks.each do |hook|
|
83
|
+
ws.send({type:'register',id:hook}.to_json)
|
84
|
+
end
|
85
|
+
end
|
69
86
|
ws.on :message do |message|
|
70
87
|
data = nil
|
71
88
|
begin
|
72
|
-
data = JSON.parse(message.data, symbolize_names:true)
|
89
|
+
data = JSON.parse(message.data, symbolize_names: true)
|
73
90
|
rescue => ex
|
74
|
-
block.call type:'error', message: "Message received, but couldn't parse: #{ex.message}"
|
91
|
+
block.call type: 'error', message: "Message received, but couldn't parse: #{ex.message}"
|
75
92
|
end
|
76
|
-
content = data.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo }
|
93
|
+
content = data.inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo }
|
94
|
+
data[:data][:url] = "#{@host.sub('ws://','http://')}#{data[:data][:path]}" if data[:type]=='registered' && data[:data] && data[:data][:path]
|
77
95
|
block.call(content) if data && block
|
78
96
|
end
|
79
97
|
|
80
|
-
ws.
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
ws.on :close do
|
88
|
-
block.call(type:'close') if block
|
89
|
-
stop_em
|
90
|
-
end
|
98
|
+
handle_ws(ws, :error, block) { @hooks.each { |hook| ws.send({ type: 'register', id: hook }.to_json) } }
|
99
|
+
handle_ws(ws, :close, block) { stop_em }
|
100
|
+
handle_ws(ws, :error, block) { stop_em }
|
101
|
+
end
|
102
|
+
end
|
91
103
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
104
|
+
def websocket(callback_block, &socket_block)
|
105
|
+
EM.run do
|
106
|
+
ws_settings = { ping: @ping }
|
107
|
+
ws = Faye::WebSocket::Client.new(@host, nil, ws_settings)
|
108
|
+
socket_block.call(ws)
|
96
109
|
end
|
97
|
-
|
110
|
+
callback_block.call(type: 'stopped')
|
98
111
|
rescue => ex
|
99
|
-
|
112
|
+
callback_block.call type: 'error', message: ex.message
|
100
113
|
rescue Interrupt
|
101
114
|
stop
|
102
|
-
|
115
|
+
callback_block.call(type: 'stopped')
|
116
|
+
end
|
117
|
+
|
118
|
+
def handle_ws(ws, action, callback_block, &_block)
|
119
|
+
ws.on action do
|
120
|
+
callback_block.call(type: action.to_s)
|
121
|
+
end
|
103
122
|
end
|
104
|
-
end
|
123
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/websockethook_spec.rb
CHANGED
@@ -1,12 +1,78 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
|
3
2
|
require 'websockethook'
|
3
|
+
require 'securerandom'
|
4
|
+
require 'rest-client'
|
4
5
|
|
5
6
|
describe WebSocketHook do
|
7
|
+
include Wrong
|
6
8
|
|
7
9
|
it 'can initialize' do
|
8
|
-
expect
|
10
|
+
expect do
|
9
11
|
ws = WebSocketHook.new
|
10
|
-
|
12
|
+
end.to_not raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'can register a hook' do
|
16
|
+
ws = WebSocketHook.new
|
17
|
+
data = []
|
18
|
+
t = Thread.new { ws.listen { |msg| data << msg } }
|
19
|
+
|
20
|
+
eventually do
|
21
|
+
data.any? do |line|
|
22
|
+
line[:type] == 'registered'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
ws.stop
|
27
|
+
t.kill
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can register a hook with an id' do
|
31
|
+
id = "test_#{SecureRandom.hex(4)}"
|
32
|
+
ws = WebSocketHook.new
|
33
|
+
ws.register id
|
34
|
+
data = []
|
35
|
+
t = Thread.new { ws.listen { |msg| data << msg } }
|
36
|
+
|
37
|
+
eventually do
|
38
|
+
data.any? do |line|
|
39
|
+
line[:type] == 'registered' && line[:data][:id] == id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
ws.stop
|
44
|
+
t.kill
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can trigger a hook with data' do
|
48
|
+
id = "test_#{SecureRandom.hex(4)}"
|
49
|
+
ws = WebSocketHook.new
|
50
|
+
ws.register id
|
51
|
+
data = []
|
52
|
+
t = Thread.new { ws.listen { |msg| data << msg } }
|
53
|
+
hook_url = ''
|
54
|
+
|
55
|
+
check_eventually data do |line|
|
56
|
+
found = line[:type] == 'registered' && line[:data][:id] == id
|
57
|
+
hook_url = line[:data][:url] if found
|
58
|
+
found
|
59
|
+
end
|
60
|
+
|
61
|
+
RestClient.post(hook_url,this_is_a:'test')
|
62
|
+
|
63
|
+
check_eventually data do |line|
|
64
|
+
line[:type] == 'hook' && line[:data] == {this_is_a:'test'}
|
65
|
+
end
|
66
|
+
|
67
|
+
ws.stop
|
68
|
+
t.kill
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_eventually(data, &block)
|
72
|
+
eventually do
|
73
|
+
data.any? do |line|
|
74
|
+
block.yield(line)
|
75
|
+
end
|
76
|
+
end
|
11
77
|
end
|
12
|
-
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: websockethook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.01
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Skierkowski
|
@@ -66,6 +66,34 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 10.4.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: wrong
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.7.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.7.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rest-client
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.8.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.8.0
|
69
97
|
description: Listen for web hooks in your app without creating a web service.
|
70
98
|
email:
|
71
99
|
- maciej@factor.io
|