diff --git a/endpoints/registry.py b/endpoints/registry.py index 76c7d56cd..b8f3dffe2 100644 --- a/endpoints/registry.py +++ b/endpoints/registry.py @@ -10,7 +10,7 @@ from time import time from app import storage as store, image_diff_queue from auth.auth import process_auth, extract_namespace_repo_from_session from util import checksums, changes -from util.http import abort +from util.http import abort, exact_abort from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission) from data import model @@ -158,7 +158,7 @@ def put_image_layer(namespace, repository, image_id): if (store.exists(layer_path) and not image_is_uploading(repo_image)): - abort(409, 'Image already exists', issue='image-exists', image_id=image_id) + exact_abort(409, 'Image already exists') profile.debug('Storing layer data') @@ -301,11 +301,8 @@ def get_image_json(namespace, repository, image_id, headers): flask_abort(404) profile.debug('Looking up repo layer size') - try: - size = (repo_image.storage and repo_image.storage.image_size) or repo_image.image_size - headers['X-Docker-Size'] = str(size) - except OSError: - pass + size = (repo_image.storage and repo_image.storage.image_size) or repo_image.image_size + headers['X-Docker-Size'] = str(size) response = make_response(data, 200) response.headers.extend(headers) @@ -423,7 +420,7 @@ def put_image_json(namespace, repository, image_id): profile.debug('Checking if image already exists') if (store.exists(json_path) and not image_is_uploading(repo_image)): - abort(409, 'Image already exists', issue='image-exists', image_id=image_id) + exact_abort(409, 'Image already exists') set_uploading_flag(repo_image, True) diff --git a/util/http.py b/util/http.py index 2ed21d8a5..30a8cd428 100644 --- a/util/http.py +++ b/util/http.py @@ -16,6 +16,28 @@ DEFAULT_MESSAGE[404] = 'Not Found' DEFAULT_MESSAGE[409] = 'Conflict' DEFAULT_MESSAGE[501] = 'Not Implemented' + +def _abort(status_code, data_object, headers): + # Add CORS headers to all errors + options_resp = current_app.make_default_options_response() + headers['Access-Control-Allow-Origin'] = '*' + headers['Access-Control-Allow-Methods'] = options_resp.headers['allow'] + headers['Access-Control-Max-Age'] = str(21600) + headers['Access-Control-Allow-Headers'] = ['Authorization', 'Content-Type'] + + resp = make_response(json.dumps(data_object), status_code, headers) + + # Report the abort to the user. + flask_abort(resp) + +def exact_abort(status_code, message=None): + data = {} + + if message is not None: + data['error'] = message + + _abort(status_code, data, {}) + def abort(status_code, message=None, issue=None, headers=None, **kwargs): message = (str(message) % kwargs if message else @@ -57,14 +79,4 @@ def abort(status_code, message=None, issue=None, headers=None, **kwargs): if headers is None: headers = {} - # Add CORS headers to all errors - options_resp = current_app.make_default_options_response() - headers['Access-Control-Allow-Origin'] = '*' - headers['Access-Control-Allow-Methods'] = options_resp.headers['allow'] - headers['Access-Control-Max-Age'] = str(21600) - headers['Access-Control-Allow-Headers'] = ['Authorization', 'Content-Type'] - - resp = make_response(json.dumps(data), status_code, headers) - - # Report the abort to the user. - flask_abort(resp) + _abort(status_code, data, headers)