Class: Rack::Superfeedr
- Inherits:
-
Object
- Object
- Rack::Superfeedr
- Defined in:
- lib/rack-superfeedr.rb
Overview
This is a Rack Middleware that can be used in your rack-compatible web framework (Rails, Sinatra...) to perform subscriptions over at superfeedr using the PubSubHubbub API.
Constant Summary
- SUPERFEEDR_ENDPOINT =
"http://superfeedr.com/hubbub"
Instance Method Summary (collapse)
- - (Object) call(env)
-
- (Superfeedr) initialize(app, params = {}, &block)
constructor
When using this Rack, you need to supply the following arguments:
-
:host (the host for your web app. Used to build the callback urls.)
-
:login
-
:password
-
:format (atom|json, atom being default)
-
:async (true|false), false is default.
-
-
- (Object) on_notification(&block)
This allows you to define what happens with the notifications.
-
- (Object) subscribe(url, id, &block)
Subscribe you to a url.
-
- (Object) unsubscribe(url, id, &block)
Unsubscribes a url.
Constructor Details
- (Superfeedr) initialize(app, params = {}, &block)
When using this Rack, you need to supply the following arguments:
-
:host (the host for your web app. Used to build the callback urls.)
-
:login
-
:password
-
:format (atom|json, atom being default)
-
:async (true|false), false is default. You need to set that to false if you're using platforms like Heroku that may disallow concurrency.
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rack-superfeedr.rb', line 79 def initialize(app, params = {}, &block) raise ArgumentError, 'Missing :host in params' unless params[:host] raise ArgumentError, 'Missing :login in params' unless params[:login] raise ArgumentError, 'Missing :password in params' unless params[:password] @callback = Proc.new { |notification, feed_id| # Bh default, do nothing } @verifications = {} @params = params @app = app block.call(self) end |
Instance Method Details
- (Object) call(env)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/rack-superfeedr.rb', line 92 def call(env) req = Rack::Request.new(env) if env['REQUEST_METHOD'] == 'GET' && feed_id = env['REQUEST_PATH'].match(/\/superfeedr\/feed\/(.*)/) # Verification of intent! if @verifications[feed_id[1]] && verification = @verifications[feed_id[1]][req.params['hub.mode']] # Check with the user if verification.call(req.params['hub.topic'], feed_id[1]) Rack::Response.new(req.params['hub.challenge'], 200).finish else Rack::Response.new("not valid", 404).finish end else # By default, we accept all Rack::Response.new(req.params['hub.challenge'], 200).finish end elsif env['REQUEST_METHOD'] == 'POST' && feed_id = env['REQUEST_PATH'].match(/\/superfeedr\/feed\/(.*)/) # Notification content = nil content_type = env["CONTENT_TYPE"].split(";").first if content_type == "application/json" # Let's parse the body as JSON content = JSON.parse(req.body.read) elsif content_type == "application/atom+xml" # Let's parse the body as ATOM using nokogiri content = Nokogiri.parse(req.body.read) end # Let's now send that data back to the user. if !@callback.call(content, feed_id[1]) # We need to unsubscribe the user end Rack::Response.new("Thanks!", 200).finish else @app.call(env) end end |
- (Object) on_notification(&block)
This allows you to define what happens with the notifications. The block passed in argument is called for each notification, with 2 arguments
-
the payload itself (ATOM or JSON, based on what you selected in the params)
-
the id for the feed, if you used any upon subscription
68 69 70 |
# File 'lib/rack-superfeedr.rb', line 68 def on_notification(&block) @callback = block end |
- (Object) subscribe(url, id, &block)
Subscribe you to a url. id is optional, but recommanded has a unique identifier for this url. It will be used to help you identify which feed is concerned by a notification. The optional block will be called to let you confirm the subscription (or not). It returns true if the subscription was successful (or will be confirmed if you used async => true in the options), false otherwise
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rack-superfeedr.rb', line 19 def subscribe(url, id, &block) feed_id = "#{id ? id : Base64.urlsafe_encode64(url)}" if block @verifications[feed_id] ||= {} @verifications[feed_id]['subscribe'] = block end response = Typhoeus::Request.post(SUPERFEEDR_ENDPOINT, :params => { :hub.mode' => 'subscribe', :hub.verify' => @params[:async] ? 'async' : 'sync', :hub.topic' => url, :hub.callback' => generate_callback(url, feed_id) }, :headers => { :Accept => @params[:format] == "json" ? "application/json" : "application/atom+xml" }, :username => @params[:login], :password => @params[:password] ) @params[:async] && response.code == 202 || response.code == 204 # We return true to indicate the status. end |
- (Object) unsubscribe(url, id, &block)
Unsubscribes a url. If you used an id for the susbcription, you need to use _the same_. The optional block will be called to let you confirm the subscription (or not). This is not applicable for if you use params => true It returns true if the unsubscription was successful (or will be confirmed if you used async => true in the options), false otherwise
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rack-superfeedr.rb', line 45 def unsubscribe(url, id, &block) feed_id = "#{id ? id : Base64.urlsafe_encode64(url)}" if block @verifications[feed_id] ||= {} @verifications[feed_id]['unsubscribe'] = block end response = Typhoeus::Request.post(SUPERFEEDR_ENDPOINT, :params => { :hub.mode' => 'unsubscribe', :hub.verify' => @params[:async] ? 'async' : 'sync', :hub.topic' => url, :hub.callback' => generate_callback(url, feed_id) }, :username => @params[:login], :password => @params[:password] ) @params[:async] && response.code == 202 || response.code == 204 # We return true to indicate the status. end |