You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.6 KiB

  1. <?php
  2. function push_error(&$app, $msg) {
  3. $app->response()->status(400);
  4. echo $msg . "\n";
  5. die();
  6. }
  7. ///////////////////////////////////////////////////////////////
  8. // These are just test routes
  9. $app->get('/callback-success', function() use($app) {
  10. $params = $app->request()->params();
  11. $app->response()->status(200);
  12. echo $params['hub_challenge'];
  13. });
  14. $app->post('/callback-success', function() use($app) {
  15. $params = $app->request()->params();
  16. $app->response()->status(200);
  17. });
  18. $app->get('/callback-fail', function() use($app) {
  19. $params = $app->request()->params();
  20. $app->response()->status(404);
  21. });
  22. ///////////////////////////////////////////////////////////////
  23. function verify_push_topic_url($topic, &$app) {
  24. // If we've already seen the topic, assume it's valid and don't check it again
  25. if(!db\feed_from_url($topic)) {
  26. $topic_head = request\get_head($topic);
  27. if($topic_head && !request\response_is($topic_head['status'], 2)) {
  28. push_error($app, "The topic URL returned a " . $topic_head['status'] . " status code");
  29. } elseif(!$topic_head) {
  30. push_error($app, 'We tried to verify the topic URL exists but it didn\'t respond to a HEAD request.');
  31. }
  32. }
  33. }
  34. $app->post('/', function() use($app) {
  35. $params = $app->request()->params();
  36. switch($mode=k($params, 'hub_mode')) {
  37. case 'subscribe':
  38. case 'unsubscribe':
  39. // Sanity check the request params
  40. $topic = k($params, 'hub_topic');
  41. $callback = k($params, 'hub_callback');
  42. if(!is_valid_push_url($topic)) {
  43. push_error($app, 'Topic URL was invalid ('.$topic.')');
  44. }
  45. if(!is_valid_push_url($callback)) {
  46. push_error($app, 'Callback URL was invalid');
  47. }
  48. if($mode == 'subscribe') {
  49. verify_push_topic_url($topic, $app);
  50. // Find or create the feed given the topic URL
  51. $feed = db\find_or_create('feeds', ['feed_url'=>$topic], [
  52. 'hash' => db\random_hash(),
  53. ], true);
  54. // Find or create the subscription for this callback URL and feed
  55. $subscription = db\find_or_create('subscriptions', ['feed_id'=>$feed->id, 'callback_url'=>$callback], [
  56. 'hash' => db\random_hash()
  57. ], true);
  58. // Always set a new requested date and challenge
  59. $subscription->date_requested = db\now();
  60. $subscription->challenge = db\random_hash();
  61. db\set_updated($subscription);
  62. $subscription->save();
  63. // Queue the worker to validate the subscription
  64. DeferredTask::queue('PushTask', 'verify_subscription', [$subscription->id, 'subscribe']);
  65. } else {
  66. $feed = db\feed_from_url($topic);
  67. if(!$feed) {
  68. push_error($app, 'The topic was not found, so there is no subscription active');
  69. }
  70. $subscription = db\find('subscriptions', ['feed_id'=>$feed->id, 'callback_url'=>$callback]);
  71. if(!$subscription) {
  72. push_error($app, 'There was no subscription found for this callback URL and topic');
  73. }
  74. // Queue the worker to validate the subscription
  75. DeferredTask::queue('PushTask', 'verify_subscription', [$subscription->id, 'unsubscribe']);
  76. }
  77. $app->response()->status(202);
  78. echo "The subscription request is being validated. Check the status here:\n";
  79. echo Config::$base_url . '/subscription/' . $subscription->hash . "\n";
  80. break;
  81. case 'publish':
  82. // Sanity check the request params
  83. $url = k($params, 'hub_url');
  84. if(!$url)
  85. $url = k($params, 'hub_topic');
  86. if(!$url) {
  87. push_error($app, 'No URL was specified. When publishing, send the topic URL in a parameter named hub.topic');
  88. }
  89. if(!is_valid_push_url($url)) {
  90. push_error($app, 'URL was invalid');
  91. }
  92. verify_push_topic_url($url, $app);
  93. // Find or create the feed given the topic URL
  94. $feed = db\find_or_create('feeds', ['feed_url'=>$url], [
  95. 'hash' => db\random_hash(),
  96. ], true);
  97. $num_subscribers = ORM::for_table('subscriptions')->where('feed_id', $feed->id)->where('active', 1)->count();
  98. $feed->push_last_ping_received = db\now();
  99. db\set_updated($feed);
  100. $feed->save();
  101. // Queue the worker to ping all the subscribers about the new content
  102. DeferredTask::queue('PushTask', 'publish', $feed->id);
  103. $app->response()->status(202);
  104. echo "There are currently $num_subscribers active subscriptions for this feed.\n";
  105. echo "The hub is checking the feed for new content and notifying the subscribers.\nCheck the status here:\n";
  106. echo Config::$base_url . '/feed/' . $feed->hash . "\n";
  107. break;
  108. }
  109. });