Some code simplifications & logging for Zencoder notifications.
This commit is contained in:
parent
d7ee2121d9
commit
fd5bcaec52
@ -1,40 +1,51 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from eve.methods.put import put_internal
|
from eve.methods.put import put_internal
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from flask import abort
|
from flask import abort
|
||||||
from flask import request
|
from flask import request
|
||||||
from application import app
|
from application import app
|
||||||
|
from application import utils
|
||||||
|
|
||||||
encoding = Blueprint('encoding', __name__)
|
encoding = Blueprint('encoding', __name__)
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@encoding.route('/zencoder/notifications', methods=['POST'])
|
@encoding.route('/zencoder/notifications', methods=['POST'])
|
||||||
def zencoder_notifications():
|
def zencoder_notifications():
|
||||||
if app.config['ENCODING_BACKEND'] == 'zencoder':
|
if app.config['ENCODING_BACKEND'] != 'zencoder':
|
||||||
|
log.warning('Received notification from Zencoder but app not configured for Zencoder.')
|
||||||
|
return abort(403)
|
||||||
|
|
||||||
if not app.config['DEBUG']:
|
if not app.config['DEBUG']:
|
||||||
# If we are in production, look for the Zencoder header secret
|
# If we are in production, look for the Zencoder header secret
|
||||||
try:
|
try:
|
||||||
notification_secret_request = request.headers[
|
notification_secret_request = request.headers[
|
||||||
'X-Zencoder-Notification-Secret']
|
'X-Zencoder-Notification-Secret']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
log.warning('Received Zencoder notification without secret.')
|
||||||
return abort(401)
|
return abort(401)
|
||||||
# If the header is found, check it agains the one in the config
|
# If the header is found, check it agains the one in the config
|
||||||
notification_secret = app.config['ZENCODER_NOTIFICATIONS_SECRET']
|
notification_secret = app.config['ZENCODER_NOTIFICATIONS_SECRET']
|
||||||
if notification_secret_request != notification_secret:
|
if notification_secret_request != notification_secret:
|
||||||
|
log.warning('Received Zencoder notification with incorrect secret.')
|
||||||
return abort(401)
|
return abort(401)
|
||||||
|
|
||||||
# Cast request data into a dict
|
# Cast request data into a dict
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
files_collection = app.data.driver.db['files']
|
files_collection = app.data.driver.db['files']
|
||||||
# Find the file object based on processing backend and job_id
|
# Find the file object based on processing backend and job_id
|
||||||
lookup = {'processing.backend': 'zencoder', 'processing.job_id': str(
|
lookup = {'processing.backend': 'zencoder', 'processing.job_id': str(data['job']['id'])}
|
||||||
data['job']['id'])}
|
|
||||||
f = files_collection.find_one(lookup)
|
f = files_collection.find_one(lookup)
|
||||||
if f:
|
if not f:
|
||||||
|
log.warning('Unknown Zencoder job id %r', data['job']['id'])
|
||||||
|
return abort(404)
|
||||||
|
|
||||||
file_id = f['_id']
|
file_id = f['_id']
|
||||||
# Remove internal keys (so that we can run put internal)
|
# Remove internal keys (so that we can run put internal)
|
||||||
internal_fields = ['_id', '_etag', '_updated', '_created', '_status']
|
f = utils.remove_private_keys(f)
|
||||||
for field in internal_fields:
|
|
||||||
f.pop(field, None)
|
|
||||||
# Update processing status
|
# Update processing status
|
||||||
f['processing']['status'] = data['job']['state']
|
f['processing']['status'] = data['job']['state']
|
||||||
# For every variation encoded, try to update the file object
|
# For every variation encoded, try to update the file object
|
||||||
@ -50,9 +61,5 @@ def zencoder_notifications():
|
|||||||
if variation:
|
if variation:
|
||||||
variation['length'] = output['file_size_in_bytes']
|
variation['length'] = output['file_size_in_bytes']
|
||||||
|
|
||||||
r = put_internal('files', f, **{'_id': ObjectId(file_id)})
|
put_internal('files', f, _id=ObjectId(file_id))
|
||||||
return ''
|
return ''
|
||||||
else:
|
|
||||||
return abort(404)
|
|
||||||
else:
|
|
||||||
return abort(403)
|
|
||||||
|
50
tests/test_encoding.py
Normal file
50
tests/test_encoding.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""Test cases for the zencoder notifications."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
from common_test_class import AbstractPillarTest
|
||||||
|
|
||||||
|
|
||||||
|
class ZencoderNotificationTest(AbstractPillarTest):
|
||||||
|
|
||||||
|
def test_missing_secret(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
resp = self.client.post('/encoding/zencoder/notifications')
|
||||||
|
self.assertEqual(401, resp.status_code)
|
||||||
|
|
||||||
|
def test_wrong_secret(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
resp = self.client.post('/encoding/zencoder/notifications',
|
||||||
|
headers={'X-Zencoder-Notification-Secret': 'koro'})
|
||||||
|
self.assertEqual(401, resp.status_code)
|
||||||
|
|
||||||
|
def test_good_secret_missing_file(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
secret = self.app.config['ZENCODER_NOTIFICATIONS_SECRET']
|
||||||
|
resp = self.client.post('/encoding/zencoder/notifications',
|
||||||
|
data=json.dumps({'job': {'id': 'koro-007'}}),
|
||||||
|
headers={'X-Zencoder-Notification-Secret': secret,
|
||||||
|
'Content-Type': 'application/json'})
|
||||||
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
|
def test_good_secret_existing_file(self):
|
||||||
|
self.ensure_file_exists(file_overrides={
|
||||||
|
'processing': {'backend': 'zencoder',
|
||||||
|
'job_id': 'koro-007',
|
||||||
|
'status': 'processing'}
|
||||||
|
})
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
|
secret = self.app.config['ZENCODER_NOTIFICATIONS_SECRET']
|
||||||
|
resp = self.client.post('/encoding/zencoder/notifications',
|
||||||
|
data=json.dumps({'job': {'id': 'koro-007',
|
||||||
|
'state': 'done'},
|
||||||
|
'outputs': [{
|
||||||
|
'format': 'jpg',
|
||||||
|
'width': 2048,
|
||||||
|
'file_size_in_bytes': 15,
|
||||||
|
}]}),
|
||||||
|
headers={'X-Zencoder-Notification-Secret': secret,
|
||||||
|
'Content-Type': 'application/json'})
|
||||||
|
|
||||||
|
# TODO: check that the file in MongoDB is actually updated properly.
|
||||||
|
self.assertEqual(200, resp.status_code)
|
Loading…
x
Reference in New Issue
Block a user