Mercurial > prosody-modules
comparison mod_pubsub_feed/mod_pubsub_feed.lua @ 323:433bf7dc3e7a
mod_pubsub_feed: Stricter verification handling. Correctly echo the hubs challenge.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Mon, 31 Jan 2011 23:11:47 +0100 |
parents | 637dc0a04052 |
children | 100b3ad2e10c |
comparison
equal
deleted
inserted
replaced
322:637dc0a04052 | 323:433bf7dc3e7a |
---|---|
30 local parse_feed = require "feeds".feed_from_string; | 30 local parse_feed = require "feeds".feed_from_string; |
31 local st = require "util.stanza"; | 31 local st = require "util.stanza"; |
32 local httpserver = require "net.httpserver"; | 32 local httpserver = require "net.httpserver"; |
33 local formencode = require "net.http".formencode; | 33 local formencode = require "net.http".formencode; |
34 local dump = require "util.serialization".serialize; | 34 local dump = require "util.serialization".serialize; |
35 local uuid = require "util.uuid".generate; | |
35 | 36 |
36 local urldecode = require "net.http".urldecode; | 37 local urldecode = require "net.http".urldecode; |
37 local urlencode = require "net.http".urlencode; | 38 local urlencode = require "net.http".urlencode; |
38 local urlparams = --require "net.http".getQueryParams or whatever MattJ names it, FIXME | 39 local urlparams = --require "net.http".getQueryParams or whatever MattJ names it, FIXME |
39 function(s) | 40 function(s) |
56 for node, url in pairs(config) do | 57 for node, url in pairs(config) do |
57 feed_list[node] = { url = url; node = node; last_update = 0 }; | 58 feed_list[node] = { url = url; node = node; last_update = 0 }; |
58 end | 59 end |
59 | 60 |
60 local response_codes = { | 61 local response_codes = { |
62 ["200"] = "OK"; | |
61 ["202"] = "Accepted"; | 63 ["202"] = "Accepted"; |
62 ["400"] = "Bad Request"; | 64 ["400"] = "Bad Request"; |
65 ["404"] = "Not Found"; | |
63 ["501"] = "Not Implemented"; | 66 ["501"] = "Not Implemented"; |
64 }; | 67 }; |
65 | 68 |
66 local function http_response(code, headers, body) | 69 local function http_response(code, headers, body) |
67 return { | 70 return { |
157 end | 160 end |
158 end | 161 end |
159 return refresh_interval; | 162 return refresh_interval; |
160 end | 163 end |
161 | 164 |
162 function subscribe(feed, challenge) | 165 function subscribe(feed) |
166 local token = uuid(); | |
163 local _body, body = { | 167 local _body, body = { |
164 ["hub.callback"] = "http://"..module.host..":5280/callback?node=" .. urlencode(feed.node); --FIXME figure out your own hostname reliably? | 168 ["hub.callback"] = "http://"..module.host..":5280/callback?node=" .. urlencode(feed.node); --FIXME figure out your own hostname reliably? |
165 ["hub.mode"] = "subscribe"; --TODO unsubscribe | 169 ["hub.mode"] = "subscribe"; --TODO unsubscribe |
166 ["hub.topic"] = feed.url; | 170 ["hub.topic"] = feed.url; |
167 ["hub.verify"] = "async"; | 171 ["hub.verify"] = "async"; |
168 ["hub.verify_token"] = challenge; | 172 ["hub.verify_token"] = token; |
173 --["hub.secret"] = ""; -- TODO http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html#authednotify | |
169 --["hub.lease_seconds"] = ""; | 174 --["hub.lease_seconds"] = ""; |
170 }, { }; | 175 }, { }; |
171 for name, value in pairs(_body) do | 176 for name, value in pairs(_body) do |
172 t_insert(body, { name = name, value = value }); | 177 t_insert(body, { name = name, value = value }); |
173 end --FIXME Why do I have to do this? | 178 end --FIXME Why do I have to do this? |
174 body = formencode(body); | 179 body = formencode(body); |
175 | 180 |
176 --module:log("debug", "subscription request, body: %s", body); | 181 --module:log("debug", "subscription request, body: %s", body); |
177 | 182 |
178 --FIXME The subscription states and related stuff | 183 --FIXME The subscription states and related stuff |
179 --feed.subscription = challenge and "asked" or "asking"; | 184 feed.subscription = "subscribe"; |
180 feed.subscription = "asking"; | |
181 http.request(feed.hub, { body = body }, function(data, code, req) | 185 http.request(feed.hub, { body = body }, function(data, code, req) |
182 local code = tostring(code); | 186 local code = tostring(code); |
183 module:log("debug", "subscription to %s submitted, staus %s", feed.node, code); | 187 module:log("debug", "subscription to %s submitted, staus %s", feed.node, code); |
184 if code == '202' then | |
185 if challenge then | |
186 module:log("debug", "subscribe to %s confirmed", feed.node); | |
187 feed.subscription = "active"; | |
188 else | |
189 module:log("debug", "subscription to %s submitted", feed.node); | |
190 --feed.subscription = "incomplete"; | |
191 end | |
192 end | |
193 end); | 188 end); |
194 end | 189 end |
195 | 190 |
196 function handle_http_request(method, body, request) | 191 function handle_http_request(method, body, request) |
197 --module:log("debug", "%s request to %s%s with body %s", method, request.url.path, request.url.query and "?" .. request.url.query or "", #body > 0 and body or "empty"); | 192 --module:log("debug", "%s request to %s%s with body %s", method, request.url.path, request.url.query and "?" .. request.url.query or "", #body > 0 and body or "empty"); |
199 if query and type(query) == "string" then | 194 if query and type(query) == "string" then |
200 query = urlparams(query); | 195 query = urlparams(query); |
201 --module:log("debug", "GET data: %s", dump(query)); | 196 --module:log("debug", "GET data: %s", dump(query)); |
202 end | 197 end |
203 | 198 |
204 -- TODO http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html#authednotify | |
205 | |
206 if method == "GET" then | 199 if method == "GET" then |
207 if query.node and feed_list[query.node] then | 200 if query.node and feed_list[query.node] then |
208 local feed = feed_list[query.node]; | 201 local feed = feed_list[query.node]; |
209 local challenge = query["hub.challenge"]; | 202 if query["hub.topic"] ~= feed.url then |
210 if challenge and feed.subscription == "asking" then | 203 module:log("debug", "Invalid topic: %s", tostring(query["hub.topic"])) |
211 module:log("debug", "got a challenge for %s: %s", feed.node, challenge); | 204 return http_response(404) |
212 subscribe(feed, challenge); | 205 end |
213 return http_response(202); | 206 if query["hub.mode"] ~= feed.subscription then |
214 end | 207 module:log("debug", "Invalid mode: %s", tostring(query["hub.mode"])) |
208 return http_response(400) | |
209 -- Would this work for unsubscribe? | |
210 -- Also, if feed.subscription is changed here, | |
211 -- it would probably invalidate the subscription | |
212 -- when/if the hub asks if it should be renewed | |
213 end | |
214 if query["hub.verify"] ~= feed.token then | |
215 module:log("debug", "Invalid verify_token: %s", tostring(query["hub.verify"])) | |
216 return http_response(401) | |
217 end | |
218 module:log("debug", "Confirming %s request to %s", feed.subscription, feed.url) | |
219 return http_response(200, nil, query["hub.challenge"]) | |
215 end | 220 end |
216 return http_response(400); | 221 return http_response(400); |
217 elseif method == "POST" then | 222 elseif method == "POST" then |
223 -- TODO http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html#authednotify | |
218 if #body > 0 and feed_list[query.node] then | 224 if #body > 0 and feed_list[query.node] then |
219 module:log("debug", "got %d bytes PuSHed for %s", #body, query.node); | 225 module:log("debug", "got %d bytes PuSHed for %s", #body, query.node); |
220 local feed = feed_list[query.node]; | 226 local feed = feed_list[query.node]; |
221 feed.data = body; | 227 feed.data = body; |
222 update_entry(feed); | 228 update_entry(feed); |