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); |
