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