Complete WebSub Guide

Implement real-time push notifications for RSS/Atom feeds using the WebSub (PubSubHubbub) protocol with HuntFeed.

What is WebSub?

WebSub (previously known as PubSubHubbub) is an open standard for:

  • Push-based distribution of content changes
  • Hub-mediated publication workflows
  • Real-time notifications instead of polling
Benefits for HuntFeed
  • Real-time updates - Get news immediately when published
  • Reduced bandwidth - No empty polling requests
  • Lower latency - Instant notification delivery
  • Better UX - Users see content faster
  • Scalable - Hub handles distribution to many subscribers

Architecture

┌─────────────────────────────────────────────────────┐
│                  WebSub System                      │
├─────────────────────────────────────────────────────┤
│                                                     │
│  WebSubSubscriber                                   │
│  ├─ subscribe()                                     │
│  ├─ unsubscribe()                                   │
│  ├─ verifyChallenge()                               │
│  ├─ handleNotification()                            │
│  └─ detectHubFromFeed()                             │
│                                                     │
│  WebSubManager (Orchestration)                      │
│  ├─ registerFeedWithWebSub()                        │
│  ├─ registerMultipleFeeds()                         │
│  ├─ getSubscriptionStatus()                         │
│  └─ handleWebSubNotification()                      │
│                                                     │
│  WebSubHandler (HTTP Endpoint)                      │
│  ├─ GET (verification challenge)                    │
│  └─ POST (push notification)                        │
│                                                     │
└─────────────────────────────────────────────────────┘
                        

Components

WebSubSubscriber

Core subscription management, handles hub communication, subscription lifecycle.

WebSubManager

Orchestration layer, manages multiple subscriptions, handles notification distribution.

WebSubHandler

HTTP endpoint handling, verification challenges, notification reception.

Workflow

1

Discovery

Your app fetches the feed and discovers the WebSub hub:

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Example Feed</title>
    <link rel="hub" href="https://hub.example.com/" />
    <link rel="self" href="https://example.com/feed.xml" />
    ...
</feed>
2

Subscription

Your app subscribes to the hub:

POST /hub HTTP/1.1
Host: hub.example.com

hub.callback=https://your-domain.com/websub-callback.php
hub.mode=subscribe
hub.topic=https://example.com/feed.xml
hub.lease_seconds=86400
hub.secret=your_secret_key
3

Verification

Hub verifies your callback endpoint:

GET /websub-callback.php?hub.mode=subscribe&
hub.topic=https://example.com/feed.xml&
hub.challenge=random_challenge_string&
hub.lease_seconds=86400
4

Notification

Hub pushes updates when feed changes:

POST /websub-callback.php HTTP/1.1
Host: your-domain.com
Content-Type: application/atom+xml
X-Hub-Signature: sha1=hmac_signature

<feed>...updated feed content...</feed>

Implementation Guide

Basic Setup

use Hosseinhunta\Huntfeed\Hub\FeedManager;
use Hosseinhunta\Huntfeed\WebSub\WebSubManager;

// Initialize
$feedManager = new FeedManager();
$callbackUrl = 'https://your-domain.com/websub-callback.php';

$webSubManager = new WebSubManager($feedManager, $callbackUrl);

// Configure
$webSubManager
    ->setAutoSubscribe(true)           // Auto-subscribe to hubs
    ->setFallbackToPolling(true)       // Fallback if no hub
    ->setLeaseSeconds(86400);          // 24-hour subscription

Callback Endpoint

Create websub-callback.php:

use Hosseinhunta\Huntfeed\Hub\FeedManager;
use Hosseinhunta\Huntfeed\WebSub\WebSubManager;
use Hosseinhunta\Huntfeed\WebSub\WebSubHandler;

// Setup
$feedManager = new FeedManager();
$callbackUrl = 'https://your-domain.com/websub-callback.php';
$webSubManager = new WebSubManager($feedManager, $callbackUrl);
$handler = $webSubManager->getHandler();

// Get request data
$method = $_SERVER['REQUEST_METHOD'];
$body = file_get_contents('php://input');
$headers = getallheaders();

// Process request
$result = $handler->processRequest($method, $_GET, $body, $headers);

// Handle verification
if ($method === 'GET') {
    http_response_code($result['status'] ?? 200);
    echo $result['challenge'] ?? '';
    exit;
}

// Handle notification
if ($method === 'POST') {
    $notification = $webSubManager->handleWebSubNotification(
        $body,
        $headers,
        function($items) {
            foreach ($items as $item) {
                // Process each item
                processNewItem($item);
            }
        }
    );
    
    http_response_code($notification['success'] ? 204 : 400);
    exit;
}

Hub Detection

HuntFeed automatically detects hubs in feeds:

$hubUrl = WebSubSubscriber::detectHubFromFeed($feedContent);

if ($hubUrl) {
    echo "WebSub hub found: $hubUrl";
    // Subscribe to this hub
} else {
    echo "No WebSub hub found, falling back to polling";
    // Fallback to polling
}

Security Considerations

Signature Verification

HuntFeed automatically verifies HMAC-SHA1 signatures:

// HuntFeed automatically handles this internally:
// Calculate HMAC-SHA1 of body with secret:
$expectedSignature = hash_hmac('sha1', $body, $secret);
$requestSignature = $headers['X-Hub-Signature'];

if (!hash_equals($expectedSignature, $requestSignature)) {
    // Reject notification
    http_response_code(403);
    exit;
}

Best Practices

  • Always use HTTPS in production
  • Validate signatures for each notification
  • Use strong secrets (32-byte random strings)
  • Store secrets securely (environment variables)
  • Implement rate limiting on callback endpoint
  • Log all subscription activities for auditing
  • Monitor hub availability and health

Performance Comparison

Metric Traditional Polling WebSub with HuntFeed
Requests (no updates) ∞ (every poll interval) 0 (push only)
Update Latency Minutes to hours < 1 second
Bandwidth Usage High (full feed transfers) Very Low (push notifications)
Server Load High (continuous polling) Low (event-driven)
Real-time Updates ❌ No ✅ Yes
Scaling Difficult Easy

Optimization Tips

  1. Cache subscriptions - Store in database to survive restarts
  2. Queue processing - Use background jobs for notifications
  3. Batch inserts - Insert items in batches, not individually
  4. Index smartly - Pre-index common search fields
  5. Monitor health - Track subscription renewals and failures

Troubleshooting

Common Issues

"No WebSub Hub Found"

  • Check feed contains <link rel="hub" />
  • Verify hub URL is valid and accessible
  • Some feeds don't have hubs - fallback to polling works fine

"Subscription Verification Failed"

  • Ensure callback URL is publicly accessible
  • Check firewall allows incoming requests
  • Verify HTTP method (should be GET for verification)
  • Return HTTP 200 with challenge in body

"Notification Not Received"

  • Verify subscription was verified
  • Check callback URL in subscription request
  • Ensure endpoint returns HTTP 204
  • Monitor server logs for incoming requests

"Signature Verification Failed"

  • Confirm secret matches subscription request
  • Check HMAC algorithm (should be sha1)
  • Verify header format: sha1=<signature>
  • Ensure hub sends X-Hub-Signature header