# standard imports import json import ssl import os import urllib from urllib import request from urllib.request import urlopen # third-party imports from . import Callback import celery celery_app = celery.current_app logg = celery_app.log.get_default_logger() @celery_app.task(base=Callback, bind=True) def http(self, result, url, status_code): """A generic web callback implementation for task results. Input parameters depend on whether the callback is used as an error callback, or as a part of a celery chain. The callback receives: { 'root_id': the uuid of the topmost task in the chain, which is known to the API caller. 'status': , 'result': , } :param result: Task context object (on error) or return value of previous task (on success) :type result: Varies :param url: Url to HTTP POST results to :type url: str :param status_code: 0 on success, any other value is error :type status_code: int """ req = request.Request(url) data = { 'root_id': self.request.root_id, 'status': status_code, 'result': result, } data_str = json.dumps(data) data_bytes = data_str.encode('utf-8') req.add_header('Content-Type', 'application/json') req.data = data_bytes ctx = None if self.ssl: ctx = ssl.SSLContext() ctx.load_cert_chain( self.ssl_cert_file, self.ssl_key_file, self.ssl_password, ) response = urlopen( req, context=ctx, ) if response.status != 200: raise RuntimeError('Expected status 200 from remote server, but got {} {}'.format(response.status, response.msg))