rack-superfeedr 0.4.0 → 0.4.1

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -2,13 +2,7 @@ require 'base64'
2
2
  require 'net/http'
3
3
  require 'uri'
4
4
 
5
- module Rack
6
-
7
-
8
- ##
9
- # This is a Rack Middleware that can be used in your rack-compatible web framework (Rails, Sinatra...) to perform subscriptions over at superfeedr
10
- # using the PubSubHubbub API.
11
- class Superfeedr
5
+ module SuperfeedrAPI
12
6
 
13
7
  @@superfeedr_endpoint = "https://push.superfeedr.com/"
14
8
  @@port = 80
@@ -18,135 +12,225 @@ module Rack
18
12
  @@login = nil
19
13
  @@password = nil
20
14
 
21
- def self.superfeedr_endpoint= _superfeedr_endpoint
15
+ def superfeedr_endpoint= _superfeedr_endpoint
22
16
  @@superfeedr_endpoint = _superfeedr_endpoint
23
17
  end
24
18
 
25
- def self.port= _port
19
+ def superfeedr_endpoint
20
+ @@superfeedr_endpoint
21
+ end
22
+
23
+ def port= _port
26
24
  @@port = _port
27
25
  end
28
26
 
29
- def self.host= _host
27
+ def port
28
+ @@port
29
+ end
30
+
31
+ def host= _host
30
32
  @@host = _host
31
33
  end
32
34
 
33
- def self.base_path= _base_path
35
+ def host
36
+ @@host
37
+ end
38
+
39
+ def base_path= _base_path
34
40
  @@base_path = _base_path
35
41
  end
36
42
 
37
- def self.scheme= _scheme
43
+ def base_path
44
+ @@base_path
45
+ end
46
+
47
+ def scheme= _scheme
38
48
  @@scheme = _scheme
39
49
  end
40
50
 
41
- def self.login= _login
51
+ def scheme
52
+ @@scheme
53
+ end
54
+
55
+ def login= _login
42
56
  @@login = _login
43
57
  end
44
58
 
45
- def self.password= _password
59
+ def login
60
+ @@login
61
+ end
62
+
63
+ def password= _password
46
64
  @@password = _password
47
65
  end
48
66
 
49
- ##
50
- # Subscribe you to a url. id is optional but strongly recommanded has a unique identifier for this url. It will be used to help you identify which feed
51
- # is concerned by a notification.
52
- # A 3rd options argument can be supplied with
53
- # - retrieve => true if you want to retrieve the previous items in the feed
54
- # - format => 'json' or 'atom' to specify the format of the notifications, defaults to atom
55
- # - secret => a secret string used to compyte HMAC signatures so you can check that the data is coming from Superfeedr
56
- # - sync => true (defaults to false) if you want to perfrom a verification of intent syncrhonously
57
- # - async => true (defaults to false) if you want to perfrom a verification of intent asyncrhonously
58
- # - hub => if you want to use an explicit hub, defaults to Superfeedr's http://push.superfeedr.com
59
- # It yields 3 arguments to a block:
60
- # - body of the response (useful if you used the retrieve option)
61
- # - success flag
62
- # - response (useful to debug failed requests mostly)
63
- def self.subscribe(url, id = nil, opts = {}, &blk)
64
- endpoint = opts[:hub] || @@superfeedr_endpoint
65
- request = prep_request(url, id, endpoint, opts)
66
-
67
- if opts[:retrieve]
68
- request['retrieve'] = true
69
- end
70
-
71
- if opts[:format] == "json"
72
- request['format'] = "json"
73
- end
67
+ def password
68
+ @@password
69
+ end
74
70
 
75
- if opts[:secret]
76
- request['hub.secret'] = opts[:secret]
77
- else
78
- request['hub.secret'] = "WHAT DO WE PICK? A UNIQUE SCRET THE CALLBACK? SO WE CAN USE THAT ON NOTIFS?"
79
- end
80
-
81
- request['hub.mode'] = 'subscribe'
71
+ ##
72
+ # Subscribe you to a url. id is optional but strongly recommanded has a unique identifier for this url. It will be used to help you identify which feed
73
+ # is concerned by a notification.
74
+ # A 3rd options argument can be supplied with
75
+ # - retrieve => true if you want to retrieve the previous items in the feed
76
+ # - format => 'json' or 'atom' to specify the format of the notifications, defaults to atom
77
+ # - secret => a secret string used to compyte HMAC signatures so you can check that the data is coming from Superfeedr
78
+ # - sync => true (defaults to false) if you want to perfrom a verification of intent syncrhonously
79
+ # - async => true (defaults to false) if you want to perfrom a verification of intent asyncrhonously
80
+ # - hub => if you want to use an explicit hub, defaults to Superfeedr's http://push.superfeedr.com
81
+ # It yields 3 arguments to a block:
82
+ # - body of the response (useful if you used the retrieve option)
83
+ # - success flag
84
+ # - response (useful to debug failed requests mostly)
85
+ def subscribe(url, id = nil, opts = {}, &blk)
86
+ endpoint = opts[:hub] || @@superfeedr_endpoint
87
+ request = prep_request(url, id, endpoint, opts)
88
+
89
+ if opts[:retrieve]
90
+ request['retrieve'] = true
91
+ end
92
+
93
+ if opts[:format] == "json"
94
+ request['format'] = "json"
95
+ end
96
+
97
+ if opts[:secret]
98
+ request['hub.secret'] = opts[:secret]
99
+ else
100
+ request['hub.secret'] = "WHAT DO WE PICK? A UNIQUE SCRET THE CALLBACK? SO WE CAN USE THAT ON NOTIFS?"
101
+ end
102
+
103
+ request['hub.mode'] = 'subscribe'
104
+
105
+ response = http_post(endpoint, request)
82
106
 
83
- response = http_post(endpoint, request)
107
+ blk.call(response.body, opts[:async] && Integer(response.code) == 202 || Integer(response.code) == 204 || opts[:retrieve] && Integer(response.code) == 200, response) if blk
108
+ end
84
109
 
85
- blk.call(response.body, opts[:async] && Integer(response.code) == 202 || Integer(response.code) == 204 || opts[:retrieve] && Integer(response.code) == 200, response) if blk
110
+ ##
111
+ # Retrieve the content of a resource at Superfeedr
112
+ # A 2nd options argument can be supplied with
113
+ # - format => 'json' or 'atom' to specify the format of the notifications, defaults to atom
114
+ # - count => Integer (number of items to retrieve)
115
+ # - before => The id of an entry in the feed. The response will only include entries published before this one.
116
+ # - after => The id of an entry in the feed. The response will only include entries published after this one.
117
+ # It yields 3 arguments to a block (if block is supplied. If not, just returns the triplet)
118
+ # - body of the response (useful if you used the retrieve option)
119
+ # - success flag
120
+ # - response (useful to debug failed requests mostly)
121
+ def retrieve_by_topic_url(url, opts = {}, &blk)
122
+ endpoint = opts[:hub] || @@superfeedr_endpoint
123
+ request = prep_request(url, '', endpoint, opts)
124
+
125
+ if opts[:format] == "json"
126
+ request['format'] = "json"
86
127
  end
87
128
 
88
- ##
89
- # Retrieve the content of a resource at Superfeedr
90
- # A 2nd options argument can be supplied with
91
- # - format => 'json' or 'atom' to specify the format of the notifications, defaults to atom
92
- # - count => Integer (number of items to retrieve)
93
- # - before => The id of an entry in the feed. The response will only include entries published before this one.
94
- # - after => The id of an entry in the feed. The response will only include entries published after this one.
95
- # It yields 3 arguments to a block (if block is supplied. If not, just returns the triplet)
96
- # - body of the response (useful if you used the retrieve option)
97
- # - success flag
98
- # - response (useful to debug failed requests mostly)
99
- def self.retrieve_by_topic_url(url, opts = {}, &blk)
100
- endpoint = opts[:hub] || @@superfeedr_endpoint
101
- request = prep_request(url, '', endpoint, opts)
102
-
103
- if opts[:format] == "json"
104
- request['format'] = "json"
105
- end
129
+ if opts[:count]
130
+ request['count'] = opts[:count]
131
+ else
132
+ request['count'] = 10
133
+ end
134
+
135
+ request['hub.mode'] = 'retrieve'
106
136
 
107
- if opts[:count]
108
- request['count'] = opts[:count]
109
- else
110
- request['count'] = 10
111
- end
112
-
113
- request['hub.mode'] = 'retrieve'
137
+ response = http_get(endpoint, request)
114
138
 
115
- response = http_get(endpoint, request)
139
+ if blk
140
+ blk.call(response.body, Integer(response.code) == 200, response) if blk
141
+ else
142
+ [response.body, Integer(response.code) == 200, response]
143
+ end
144
+ end
116
145
 
117
- if blk
118
- blk.call(response.body, Integer(response.code) == 200, response) if blk
119
- else
120
- [response.body, Integer(response.code) == 200, response]
121
- end
146
+ ##
147
+ # Unsubscribes a url. If you used an id for the susbcription, you need to use _the same_.
148
+ # The optional block will be called to let you confirm the subscription (or not). This is not applicable for if you use params[:async] => true
149
+ # It returns true if the unsubscription was successful (or will be confirmed if you used async => true in the options), false otherwise
150
+ # You can also pass an opts third argument that will be merged with the options used in Typhoeus's Request (https://github.com/dbalatero/typhoeus)
151
+
152
+ ##
153
+ # Subscribe you to a url. id needs to match the id you used to subscribe.
154
+ # A 3rd options argument can be supplied with
155
+ # - sync => true (defaults to false) if you want to perfrom a verification of intent syncrhonously
156
+ # - async => true (defaults to false) if you want to perfrom a verification of intent asyncrhonously
157
+ # - hub => if you want to use an explicit hub, defaults to Superfeedr's http://push.superfeedr.com
158
+ # It yields 3 arguments to a block:
159
+ # - body of the response (useful to debug failed notifications)
160
+ # - success flag
161
+ # - response (useful to debug failed requests mostly)
162
+ def unsubscribe(url, id = nil, opts = {}, &blk)
163
+ endpoint = opts[:hub] || @@superfeedr_endpoint
164
+ request = prep_request(url, id, endpoint, opts)
165
+
166
+ request['hub.mode'] = 'unsubscribe'
167
+
168
+ response = http_post(endpoint, request)
169
+
170
+ blk.call(response.body, opts[:async] && Integer(response.code) == 202 || Integer(response.code) == 204, response) if blk
171
+ end
172
+
173
+ protected
174
+
175
+ def prep_request(url, id, endpoint, opts)
176
+ feed_id = "#{id ? id : Base64.urlsafe_encode64(url)}"
177
+
178
+ request = {
179
+ 'hub.topic' => url,
180
+ 'hub.callback' => generate_callback(url, feed_id)
181
+ }
182
+
183
+ if endpoint == @@superfeedr_endpoint && @@login && @@password
184
+ request['authorization'] = Base64.encode64( "#{@@login}:#{@@password}" ).chomp
122
185
  end
123
186
 
124
- ##
125
- # Unsubscribes a url. If you used an id for the susbcription, you need to use _the same_.
126
- # The optional block will be called to let you confirm the subscription (or not). This is not applicable for if you use params[:async] => true
127
- # It returns true if the unsubscription was successful (or will be confirmed if you used async => true in the options), false otherwise
128
- # You can also pass an opts third argument that will be merged with the options used in Typhoeus's Request (https://github.com/dbalatero/typhoeus)
129
-
130
- ##
131
- # Subscribe you to a url. id needs to match the id you used to subscribe.
132
- # A 3rd options argument can be supplied with
133
- # - sync => true (defaults to false) if you want to perfrom a verification of intent syncrhonously
134
- # - async => true (defaults to false) if you want to perfrom a verification of intent asyncrhonously
135
- # - hub => if you want to use an explicit hub, defaults to Superfeedr's http://push.superfeedr.com
136
- # It yields 3 arguments to a block:
137
- # - body of the response (useful to debug failed notifications)
138
- # - success flag
139
- # - response (useful to debug failed requests mostly)
140
- def self.unsubscribe(url, id = nil, opts = {}, &blk)
141
- endpoint = opts[:hub] || @@superfeedr_endpoint
142
- request = prep_request(url, id, endpoint, opts)
143
-
144
- request['hub.mode'] = 'unsubscribe'
145
-
146
- response = http_post(endpoint, request)
147
-
148
- blk.call(response.body, opts[:async] && Integer(response.code) == 202 || Integer(response.code) == 204, response) if blk
187
+ if opts[:async]
188
+ request['hub.verify'] = 'async'
189
+ end
190
+
191
+ if opts[:sync]
192
+ request['hub.verify'] = 'sync'
193
+ end
194
+
195
+ request
196
+ end
197
+
198
+ def http_get(url, opts)
199
+ uri = URI.parse URI.encode(url)
200
+ uri.query = URI.encode_www_form opts || {}
201
+ uri.path=='/' if uri.path.empty?
202
+ http = Net::HTTP.new(uri.host, uri.port)
203
+ http.use_ssl = true
204
+ request = Net::HTTP::Get.new uri.request_uri
205
+ http.request(request)
206
+ end
207
+
208
+ def http_post(url, opts)
209
+ uri = URI.parse URI.encode(url)
210
+ uri.path=='/' if uri.path.empty?
211
+ http = Net::HTTP.new(uri.host, uri.port)
212
+ http.use_ssl = true
213
+ request = Net::HTTP::Post.new uri.request_uri
214
+ request.set_form_data (opts||{})
215
+ http.request(request)
216
+ end
217
+
218
+ def generate_callback(url, feed_id)
219
+ if @@scheme == "https"
220
+ URI::HTTPS.build({:scheme => @@scheme, :host => @@host, :path => "#{@@base_path}#{feed_id}", :port => @@port }).to_s
221
+ else
222
+ URI::HTTP.build({:scheme => @@scheme, :host => @@host, :path => "#{@@base_path}#{feed_id}", :port => @@port }).to_s
149
223
  end
224
+ end
225
+ end
226
+
227
+
228
+ module Rack
229
+
230
+ ##
231
+ # This is a Rack Middleware that can be used in your rack-compatible web framework (Rails, Sinatra...) to perform subscriptions over at superfeedr
232
+ # using the PubSubHubbub API.
233
+ class Superfeedr
150
234
 
151
235
  ##
152
236
  # This allows you to define what happens with the notifications. The block passed in argument is called for each notification, with 4 arguments
@@ -203,13 +287,13 @@ module Rack
203
287
  # Called by Rack!
204
288
  def call(env)
205
289
  req = Rack::Request.new(env)
206
- if env['REQUEST_METHOD'] == 'GET' && feed_id = env['PATH_INFO'].match(/#{@@base_path}(.*)/)
290
+ if env['REQUEST_METHOD'] == 'GET' && feed_id = env['PATH_INFO'].match(/#{Rack::Superfeedr.base_path}(.*)/)
207
291
  if @verification.call(req.params['hub.mode'], feed_id[1], req.params['hub.topic'], req)
208
292
  Rack::Response.new(req.params['hub.challenge'], 200).finish
209
293
  else
210
294
  Rack::Response.new("not valid", 404).finish
211
295
  end
212
- elsif env['REQUEST_METHOD'] == 'POST' && feed_id = env['PATH_INFO'].match(/#{@@base_path}(.*)/)
296
+ elsif env['REQUEST_METHOD'] == 'POST' && feed_id = env['PATH_INFO'].match(/#{Rack::Superfeedr.base_path}(.*)/)
213
297
  @callback.call(feed_id[1], req.body.read, req.env['HTTP_X_PUBSUBHUBBUB_TOPIC'], req)
214
298
  Rack::Response.new("Thanks!", 200).finish
215
299
  else
@@ -217,57 +301,8 @@ module Rack
217
301
  end
218
302
  end
219
303
 
220
- protected
221
-
222
- def self.prep_request(url, id, endpoint, opts)
223
- feed_id = "#{id ? id : Base64.urlsafe_encode64(url)}"
224
-
225
- request = {
226
- 'hub.topic' => url,
227
- 'hub.callback' => generate_callback(url, feed_id)
228
- }
229
-
230
- if endpoint == @@superfeedr_endpoint && @@login && @@password
231
- request['authorization'] = Base64.encode64( "#{@@login}:#{@@password}" ).chomp
232
- end
304
+ extend SuperfeedrAPI
233
305
 
234
- if opts[:async]
235
- request['hub.verify'] = 'async'
236
- end
237
-
238
- if opts[:sync]
239
- request['hub.verify'] = 'sync'
240
- end
241
-
242
- request
243
- end
244
-
245
- def self.http_get(url, opts)
246
- uri = URI.parse URI.encode(url)
247
- uri.query = URI.encode_www_form opts || {}
248
- uri.path=='/' if uri.path.empty?
249
- http = Net::HTTP.new(uri.host, uri.port)
250
- http.use_ssl = true
251
- request = Net::HTTP::Get.new uri.request_uri
252
- http.request(request)
253
- end
254
-
255
- def self.http_post(url, opts)
256
- uri = URI.parse URI.encode(url)
257
- uri.path=='/' if uri.path.empty?
258
- http = Net::HTTP.new(uri.host, uri.port)
259
- http.use_ssl = true
260
- request = Net::HTTP::Post.new uri.request_uri
261
- request.set_form_data (opts||{})
262
- http.request(request)
263
- end
264
-
265
- def self.generate_callback(url, feed_id)
266
- if @@scheme == "https"
267
- URI::HTTPS.build({:scheme => @@scheme, :host => @@host, :path => "#{@@base_path}#{feed_id}", :port => @@port }).to_s
268
- else
269
- URI::HTTP.build({:scheme => @@scheme, :host => @@host, :path => "#{@@base_path}#{feed_id}", :port => @@port }).to_s
270
- end
271
- end
272
306
  end
273
307
  end
308
+
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "rack-superfeedr"
8
- s.version = "0.4.0"
8
+ s.version = "0.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["julien51"]
12
- s.date = "2015-04-15"
12
+ s.date = "2015-04-16"
13
13
  s.description = "A gem that provides a rack middleware to interract with Superfeedr's API. "
14
14
  s.email = "julien@superfeedr.com"
15
15
  s.extra_rdoc_files = [
@@ -3,7 +3,7 @@ require 'rack'
3
3
  require_relative 'helper.rb'
4
4
 
5
5
  # To run tests locally, we're using runscope's passageway which proxies requests inside the firewall. (make sure you bind to port 4567)
6
- HOST = '5f83728c358.b.passageway.io'
6
+ HOST = '39fbb9eba21.b.passageway.io'
7
7
  PORT = 80
8
8
  # Also, we need superfeedr credentials.
9
9
  LOGIN = 'demo'
@@ -22,6 +22,11 @@ end
22
22
 
23
23
  # Run an app in a thread
24
24
  Thread.new do
25
+ opts = {
26
+ :Port => 4567,
27
+ # Logger: WEBrick::Log.new("/dev/null"),
28
+ AccessLog: []
29
+ }
25
30
  Rack::Handler::WEBrick.run(Rack::Superfeedr.new(MyRackApp.new) do |superfeedr|
26
31
 
27
32
  superfeedr.on_verification do |mode, feed_id, url, request|
@@ -39,7 +44,7 @@ Thread.new do
39
44
  end
40
45
 
41
46
 
42
- end, :Port => 4567, Logger: WEBrick::Log.new("/dev/null"), AccessLog: [],)
47
+ end, opts)
43
48
  end
44
49
  sleep 3
45
50
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-superfeedr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-04-15 00:00:00.000000000 Z
12
+ date: 2015-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -159,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
159
159
  version: '0'
160
160
  segments:
161
161
  - 0
162
- hash: 3582772756696706427
162
+ hash: 1123161724621889271
163
163
  required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  none: false
165
165
  requirements: