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
parent 322:637dc0a04052
child 324: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);