Example #1
0
def update_pubsub_state(feed, context):
    """
    perform any (un/re)subscription needed based on the 
    state of the feed given and currently listed 
    hubs.
    """
    hubs = feed.find_hub_urls()
    ps = feed.hub_info

    # if pubsub is disabled for this feed
    if not ps.enabled:
        if ps.subscribed: 
            try:
                hubbub_unsub(feed, context)
            except:
                log.warn("Error unsubscribing from hub %s for feed %s: %s" % 
                         (ps.hub_url, feed.url, traceback.format_exc()))  
        return

    # if the currently subscribed hub is no longer 
    # listed in the feed, unsubscribe from it.
    if ps.subscribed and ps.hub_url not in hubs:
        try:
            hubbub_unsub(feed, context)
        except:
            log.warn("Error unsubscribing from current hub: %s" % 
                     traceback.format_exc())
        feed = RemoteFeed.get(feed.id, context) # refresh

    # if it is time to resubscribe to the current hub, try to 
    # resubscribe
    elif ps.subscribed and datetime.utcnow() > ps.next_sub_time: 
        log.info('resubscribe %s to hub %s' % (feed.url, feed.hub_info.hub_url))
        if not _sub_any(feed, [feed.hub_info.hub_url], context):
            log.warn("Failed to resubscribe to %s for feed %s." % (ps.hub_url, feed.url))
            try:
                hubbub_unsub(feed, context)
            except:
                log.warn("Error unsubscribing from hub %s for feed %s: %s" % 
                         (ps.hub_url, feed.url, traceback.format_exc()))  
                feed = RemoteFeed.get(feed.id, context) # refresh

    # if it is not subscribed, subscribe to first thing 
    # that works.
    if not ps.subscribed:
        _sub_any(feed, hubs, context)                
Example #2
0
def test_sub_push(ctx):
    from httplib2 import Http
    from eventlet import sleep, spawn
    from melk.util.nonce import nonce_str
    from melkman.db import RemoteFeed
    from melkman.fetch.worker import run_feed_indexer
    from melkman.fetch.pubsubhubbub import WSGISubClient, callback_url_for, psh_digest
    
    import logging
    logging.basicConfig(level=logging.WARN)
    
    
    w = WSGISubClient(ctx)
    client = spawn(w.run)
    indexer = spawn(run_feed_indexer, ctx)
    
    http = Http()
    url = 'http://example.org/feed/0'
    content = random_atom_feed(url, 10)
    secret = nonce_str()
    
    digest = 'sha1=%s' % psh_digest(content, secret)
    cb = callback_url_for(url, ctx)
    
    assert RemoteFeed.get_by_url(url, ctx) == None
    
    # try posting something that is not subscribed
    r, c = http.request(cb, 'POST', body=content, headers={'X-Hub-Signature': digest})
    assert r.status == 200, 'Expected 200, got %d' % r.status
    sleep(1)
    # nothing should happen...
    assert RemoteFeed.get(url, ctx) == None

    # set up the feed, but don't subscribe
    rf = RemoteFeed.create_from_url(url, ctx)
    rf.save()
    r, c = http.request(cb, 'POST', body=content, headers={'X-Hub-Signature': digest})
    assert r.status == 200, 'Expected 200, got %d' % r.status
    sleep(1)
    # nothing should happen...
    rf = RemoteFeed.get_by_url(url, ctx)
    assert len(rf.entries) == 0
    
    # now set it up 
    rf.hub_info.enabled = True
    rf.hub_info.subscribed = True
    rf.hub_info.secret = secret
    rf.save()

    # try with wrong digest...
    r, c = http.request(cb, 'POST', body=content, headers={'X-Hub-Signature': 'wrong'})
    assert r.status == 200, 'Expected 200, got %d' % r.status
    sleep(0.5)
    # nothing should happen...
    rf = RemoteFeed.get_by_url(url, ctx)
    assert len(rf.entries) == 0
    
    # try with no digest
    r, c = http.request(cb, 'POST', body=content)
    assert r.status == 200, 'Expected 200, got %d' % r.status
    sleep(0.5)
    # nothing should happen...
    rf = RemoteFeed.get_by_url(url, ctx)
    assert len(rf.entries) == 0
    
    # finally, try with correct digest
    r, c = http.request(cb, 'POST', body=content, headers={'X-Hub-Signature': digest})
    assert r.status == 200, 'Expected 200, got %d' % r.status
    sleep(0.5)
    # nothing should happen...
    rf = RemoteFeed.get_by_url(url, ctx)
    assert len(rf.entries) == 10
    for iid in melk_ids_in(content, url):
        assert iid in rf.entries 
    
    client.kill()
    client.wait()
    indexer.kill()
    indexer.wait()