Flask-Websub Documentation Release 0.4

Flask-Websub Documentation Release 0.4

Flask-WebSub Documentation Release 0.4 Marten de Vries Mar 06, 2021 Contents: 1 Examples 1 2 API 5 2.1 Hub module...............................................5 2.2 Subscriber module............................................6 2.3 Publisher module.............................................9 2.4 Errors module..............................................9 3 Further information 11 4 Useful to know 13 5 Indices and tables 15 Python Module Index 17 Index 19 i ii CHAPTER 1 Examples To run the example below, first start a celery broker. For example like this: docker run-p 6379:6379 redis:alpine Then, it is time to install the dependencies. We use a virtualenv to isolate them from the rest of the system: python3-m venv venv # create the virtualenv source venv/bin/activate # activate the virtualenv pip install Flask-WebSub[celery,redis] # install the dependencies Now our environment is set up, we can actually create a server and client file: #!/usr/bin/env python3 # server_example.py from flask import Flask, render_template, url_for # The publisher and hub are combined in the same process because it's easier. # There's no need to do so, though. from flask_websub.publisher import publisher, init_publisher from flask_websub.hub import Hub, SQLite3HubStorage from celery import Celery # app & celery app= Flask(__name__) app.config['SERVER_NAME']='localhost:8080' celery= Celery('server_example', broker='redis://localhost:6379') # initialise publisher init_publisher(app) # initialise hub # # PUBLISH_SUPPORTED is not recommended in production, as it just accepts any # link without validation, but it's but nice for testing. (continues on next page) 1 Flask-WebSub Documentation, Release 0.4 (continued from previous page) app.config['PUBLISH_SUPPORTED']= True # we could also have passed in just PUBLISH_SUPPORTED, but this is probably a # nice pattern for your app: hub= Hub(SQLite3HubStorage('server_data.sqlite3'), celery, **app.config) app.register_blueprint(hub.build_blueprint(url_prefix='/hub')) def validate_topic_existence(callback_url, topic_url, *args): with app.app_context(): if topic_url.startswith('https://websub.rocks/'): return # pass validation if topic_url != url_for('topic', _external=True): return "Topic not allowed" hub.register_validator(validate_topic_existence) hub.schedule_cleanup() # cleanup expired subscriptions once a day, by default @app.before_first_request def cleanup(): # or just cleanup manually at some point hub.cleanup_expired_subscriptions.delay() @app.route('/') @publisher() def topic(): return render_template('server_example.html') @app.route('/update_now') def update_now(): hub.send_change_notification.delay(url_for('topic', _external=True)) return "Notification send!" if __name__ =='__main__': app.run(host='0.0.0.0', port=8080) #!/usr/bin/env python3 # client_example.py from flask import Flask, url_for from flask_websub.subscriber import Subscriber, SQLite3TempSubscriberStorage, \ SQLite3SubscriberStorage, discover import sys app= Flask(__name__) app.config['SERVER_NAME']='localhost:8081' subscriber= Subscriber(SQLite3SubscriberStorage('client_data.sqlite3'), SQLite3TempSubscriberStorage('client_data.sqlite3')) app.register_blueprint(subscriber.build_blueprint(url_prefix='/callbacks')) (continues on next page) 2 Chapter 1. Examples Flask-WebSub Documentation, Release 0.4 (continued from previous page) @subscriber.add_success_handler def on_success(topic_url, callback_id, mode): print("SUCCESS!", topic_url, callback_id, mode) @subscriber.add_error_handler def on_error(topic_url, callback_id, msg): print("ERROR!", topic_url, callback_id, msg) @subscriber.add_listener def on_topic_change(topic_url, callback_id, body): print('TOPIC CHANGED!', topic_url, callback_id, body) if len(sys.argv) ==2: published_url= sys.argv[1] else: published_url='http://localhost:8080/' @app.route('/subscribe') def subscribe_route(): id= subscriber.subscribe( **discover(published_url)) return 'Subscribed.'+ url_for('renew_route', id=id, _external= True) @app.route('/renew/<id>') def renew_route(id): new_id= subscriber.renew(id) return 'Renewed:'+ url_for('unsubscribe_route', id=new_id, _external=True) @app.route('/unsubscribe/<id>') def unsubscribe_route(id): subscriber.unsubscribe(id) return 'Unsubscribed:'+ url_for('cleanup_and_renew_all', _external= True) @app.route('/cleanup_and_renew_all') def cleanup_and_renew_all(): subscriber.cleanup() # 100 days, to make sure every single subscription is renewed subscriber.renew_close_to_expiration(24 * 60 * 60 * 100) return 'Done!' if __name__ =='__main__': app.run(host='0.0.0.0', port=8081) <!DOCTYPE html> <!-- templates/server_example.html --> <html> <head> (continues on next page) 3 Flask-WebSub Documentation, Release 0.4 (continued from previous page) <title>WebSub test</title> {{ websub_self_link }} {{ websub_hub_link }} </head> <body> Hello World! </body> </html> Don’t forget to update server_example.py and client_example.py’s SERVER_NAME config variable when creating those files. Simply set them to whatever hostname the server will have (it can just be localhost). Finally, it’s time to start the applications. Each line in a different terminal (assuming the virtualenv is active in each): celery-A server_example.celery worker-l info # starts the celery worker ./server_example.py # runs the server flask application ./client_example.py # runs the client flask application You can now see the page the hub publishes by navigating to the root url of the hub server (port 8080). As it’s a static page, you can simulate updating it by navingating to /update_now. Of course, for this to do something, you need to subscribe to the URL. The subscriber server (as defined in client_example.py, port 8081) offers a /subscribe endpoint to help you with this. It will also tell you other URLs you can visit to control the subscription side of the process. 4 Chapter 1. Examples CHAPTER 2 API 2.1 Hub module class flask_websub.hub.Hub(storage, celery=None, **config) This is the API to the hub package. The constructor requires a storage object, and also accepts a couple of optional configuration values (the defaults are shown as well): • BACKOFF_BASE=8.0: When a hub URL cannot be reached, exponential backoff is used to control retry- ing. This parameter scales the whole process. Lowering it means trying more frequently, but also for a shorter time. Highering it means the reverse. • MAX_ATTEMPTS=10: The amount of attempts the retrying process makes. • PUBLISH_SUPPORTED=False: makes it possible to do a POST request to the hub endpoint with mode=publish. This is nice for testing, but as it does no input validation, you should not leave this enabled in production. • SIGNATURE_ALGORITHM=’sha512’: The algorithm to sign a content notification body with. Other possible values are sha1, sha256 and sha384. • REQUEST_TIMEOUT=3: Specifies how long to wait before considering a request to have failed. • HUB_MIN_LEASE_SECONDS: The minimal lease_seconds value the hub will accept • HUB_DEFAULT_LEASE_SECONDS: The lease_seconds value the hub will use if the subscriber does not have a preference • HUB_MAX_LEASE_SECONDS: The maximum lease_seconds value the hub will accept You can pass in a celery object too, or do that later using init_celery. It is required to do so before actually using the hub, though. User-facing properties have doc strings. Other properties should be considered implementation details. build_blueprint(url_prefix=”) Build a blueprint containing a Flask route that is the hub endpoint. 5 Flask-WebSub Documentation, Release 0.4 cleanup_expired_subscriptions Removes any expired subscriptions from the backing data store. It takes no arguments, and is a celery task. counter = count(0) endpoint_hook() Override this method to hook into the endpoint handling. Anything this method returns will be forwarded to validation functions when subscribing. init_celery(celery) Registers the celery tasks on the hub object. register_validator(f ) Register f as a validation function for subscription requests. It gets a callback_url and topic_url as its ar- guments, and should return None if the validation succeeded, or a string describing the problem otherwise. schedule_cleanup schedule_cleanup(every_x_seconds=A_DAY): schedules the celery task cleanup_expired_subscriptions as a recurring event, the frequency of which is determined by its parameter. This is not a celery task itself (as the cleanup is only scheduled), and is a convenience function. send_change_notification Allows you to notify subscribers of a change to a topic_url. This is a celery task, so you probably will actually want to call hub.send_change_notification.delay(topic_url, updated_content). The last argument is optional. If passed in, it should be an object with two properties: headers (dict-like), and content (a base64-encoded string). If left out, the updated content will be fetched from the topic url directly. class flask_websub.hub.SQLite3HubStorage(path) CLEANUP_EXPIRED_SUBSCRIPTIONS_SQL = "\n delete from hub where expiration_time <= strftime('%s', 'now')\n " DELITEM_SQL = 'delete from hub where topic_url=? and callback_url=?' GET_CALLBACKS_SQL = "\n select callback_url, secret from hub\n where topic_url=? and expiration_time > strftime('%s', 'now')\n " SETITEM_SQL = "\n insert or replace into hub(topic_url, callback_url, expiration_time,\n secret)\n values (?, ?, strftime('%s', 'now') + ?, ?)\n " TABLE_SETUP_SQL = '\n create table if not exists hub(\n topic_url text not null,\n callback_url text not null,\n secret text,\n expiration_time integer not null,\n primary

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    24 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us