def get_http_headers(url):
"""
Get HTTP headers for given url
"""
if not url:
raise BadRequest('Missing url')
url = _get_deobfuscate_item(url)
try:
validate = URLValidator(schemes=('http', 'https', 'ftp', 'ftps', 'rtsp', 'rtmp'))
validate(url)
except ValidationError:
raise BadRequest('Not a valid URL')
try:
response = ImplementationFactory.instance.get_singleton_of(
'PhishingServiceBase'
).get_http_headers(url)
schema.valid_adapter_response('PhishingServiceBase', 'get_http_headers', response)
return response
except (PhishingServiceException, schema.InvalidFormatError, schema.SchemaNotFound) as ex:
raise InternalServerError(str(ex))
python类InternalServerError()的实例源码
def iter_endpoints(graph, match_func):
"""
Iterate through matching endpoints.
The `match_func` is expected to have a signature of:
def matches(operation, ns, rule):
return True
:returns: a generator over (`Operation`, `Namespace`, rule, func) tuples.
"""
for rule in graph.flask.url_map.iter_rules():
try:
operation, ns = Namespace.parse_endpoint(rule.endpoint)
except (IndexError, ValueError, InternalServerError):
# operation follows a different convention (e.g. "static")
continue
else:
# match_func gets access to rule to support path version filtering
if match_func(operation, ns, rule):
func = graph.flask.view_functions[rule.endpoint]
yield operation, ns, rule, func
def parse_endpoint(endpoint):
"""
Convert an endpoint name into an (operation, ns) tuple.
"""
# compute the operation
parts = endpoint.split(".")
operation = Operation.from_name(parts[1])
# extract its parts
matcher = match(operation.endpoint_pattern, endpoint)
if not matcher:
raise InternalServerError("Malformed operation endpoint: {}".format(endpoint))
kwargs = matcher.groupdict()
del kwargs["operation"]
return operation, Namespace(**kwargs)
def test_werkzeug_http_error_custom_message():
"""
Custom error messages are returned.
"""
graph = create_object_graph(name="example", testing=True)
@graph.app.route("/why_me")
@graph.audit
def why_me():
raise InternalServerError("Why me?")
client = graph.app.test_client()
response = client.get("/why_me")
assert_that(response.status_code, is_(equal_to(500)))
data = loads(response.get_data().decode("utf-8"))
assert_that(data, is_(equal_to({
"code": 500,
"message": "Why me?",
"retryable": False,
"context": {"errors": []},
})))
def get_screenshot(item_id, report_id):
"""
Get screenshot for item
"""
try:
item = ReportItem.objects.get(id=item_id, report__id=report_id)
if item.itemType != 'URL':
raise BadRequest('Item is not an URL')
except (ObjectDoesNotExist, ValueError):
raise NotFound('Item not found')
try:
screenshots = ImplementationFactory.instance.get_singleton_of(
'PhishingServiceBase'
).get_screenshots(item.rawItem)
schema.valid_adapter_response('PhishingServiceBase', 'get_screenshots', screenshots)
results = {
'rawItem': item.rawItem,
'screenshots': screenshots,
}
return results
except (PhishingServiceException, schema.InvalidFormatError, schema.SchemaNotFound):
raise InternalServerError('Error while loading screenshots')
def run_flask_request(environ):
from .wsgi_aux import app
if '_wsgi.input' in environ:
environ['wsgi.input'] = BytesIO(environ['_wsgi.input'])
# Create a request context similar to that of the original request
# so that the task can have access to flask.g, flask.request, etc.
with app.request_context(environ):
# Record the fact that we are running in the Celery worker now
g.in_celery = True
# Run the route function and record the response
try:
rv = app.full_dispatch_request()
except:
# If we are in debug mode we want to see the exception
# Else, return a 500 error
if app.debug:
raise
rv = app.make_response(InternalServerError())
return (rv.get_data(), rv.status_code, rv.headers)
def upload_output(self, input, file):
"""
POST /upload_output
"""
output_id = Database.gen_id()
path = StorageManager.new_output_file(output_id, file["name"])
StorageManager.save_file(path, file["content"])
file_size = StorageManager.get_file_size(path)
try:
result = ContestManager.evaluate_output(input["task"], input["path"], path)
except:
BaseHandler.raise_exc(InternalServerError, "INTERNAL_ERROR", "Failed to evaluate the output")
Database.add_output(output_id, input["id"], path, file_size, result)
Logger.info("UPLOAD", "User %s has uploaded the output %s" % (input["token"], output_id))
return InfoHandler.patch_output(Database.get_output(output_id))
def make_world_gettable(node):
nodes_coll = current_app.data.driver.db['nodes']
node_id = node['_id']
log.debug('Ensuring the world can read node %s', node_id)
world_perms = set(node.get('permissions', {}).get('world', []))
world_perms.add('GET')
world_perms = list(world_perms)
result = nodes_coll.update_one({'_id': node_id},
{'$set': {'permissions.world': world_perms}})
if result.matched_count != 1:
log.warning('Unable to update node %s with new permissions.world=%r', node_id, world_perms)
raise wz_exceptions.InternalServerError('Unable to update node %s with new permissions' %
node_id)
def stream_to_gcs(file_id: ObjectId, file_size: int, internal_fname: str, project_id: ObjectId,
stream_for_gcs: FileType, content_type: str) \
-> typing.Tuple[GoogleCloudStorageBlob, GoogleCloudStorageBucket]:
# Upload the file to GCS.
try:
bucket = GoogleCloudStorageBucket(str(project_id))
blob = bucket.blob(internal_fname)
blob.create_from_file(stream_for_gcs, file_size=file_size, content_type=content_type)
except Exception:
log.exception('Error uploading file to Google Cloud Storage (GCS),'
' aborting handling of uploaded file (id=%s).', file_id)
update_file_doc(file_id, status='failed')
raise wz_exceptions.InternalServerError(
'Unable to stream file to Google Cloud Storage')
return blob, bucket
def render(self, exception):
"""
Render the exception
:param exception: The exception
:type exception: Exception
:return: The response
"""
if not isinstance(exception, HTTPException):
http_exception = InternalServerError()
else:
http_exception = exception
is_server_error = http_exception.code - (http_exception.code % 100) == 500
if self.app.debug and is_server_error:
if sys.version_info < (3, 0):
exc_type, exc_value, tb = sys.exc_info()
if exc_value is exception:
reraise(exc_type, exc_value, tb)
raise exception
else:
if self.app.testing and is_server_error and isinstance(exception, Exception):
http_exception.description = '%s' % exception
return http_exception.get_response()
def run_ctx_request(environ):
"""
run flask request context in celery worker
"""
from blueprints import app # wsgi.app
if '_wsgi.input' in environ:
# an input stream (file-like object) from which the HTTP request body can be read.
# detail: https://www.python.org/dev/peps/pep-0333/#environ-variables
environ['wsgi.input'] = BytesIO(environ['_wsgi.input'])
with app.request_context():
g.in_celery = True
try:
rv = app.full_dispatch_request()
except InternalServerError:
if app.debug:
raise
return app.make_response(InternalServerError())
return (rv.get_data(), rv.status_code, rv.headers)
def run_ctx_request(environ):
from blueprints import app
# environ ????
# request body ?? in-memory-buffer ???????
# ??????????
if '_wsgi.input' in environ:
environ['wsgi.input'] = BytesIO(environ['_wsgi.input'])
with app.request_context(environ):
g.in_celery = True
try:
rv = app.full_dispatch_request()
except:
if app.debug:
raise
rv = app.make_response(InternalServerError())
return (rv.get_data(), rv.status_code, rv.headers)
def run_ctx_request(environ):
from blueprints import app
# environ ????
# request body ?? in-memory-buffer ???????
# ??????????
if '_wsgi.input' in environ:
environ['wsgi.input'] = BytesIO(environ['_wsgi.input'])
with app.request_context(environ):
g.in_celery = True
try:
rv = app.full_dispatch_request()
except:
if app.debug:
raise
rv = app.make_response(InternalServerError())
return (rv.get_data(), rv.status_code, rv.headers)
def handle_exception(self, e):
"""Default exception handling that kicks in when an exception
occours that is not catched. In debug mode the exception will
be re-raised immediately, otherwise it is logged and the handler
for a 500 internal server error is used. If no such handler
exists, a default 500 internal server error message is displayed.
.. versionadded: 0.3
"""
handler = self.error_handlers.get(500)
if self.debug:
raise
self.logger.exception('Exception on %s [%s]' % (
request.path,
request.method
))
if handler is None:
return InternalServerError()
return handler(e)
def handle_exception(self, e):
"""Default exception handling that kicks in when an exception
occours that is not catched. In debug mode the exception will
be re-raised immediately, otherwise it is logged and the handler
for a 500 internal server error is used. If no such handler
exists, a default 500 internal server error message is displayed.
.. versionadded: 0.3
"""
handler = self.error_handlers.get(500)
if self.debug:
raise
self.logger.exception('Exception on %s [%s]' % (
request.path,
request.method
))
if handler is None:
return InternalServerError()
return handler(e)
def get_defendant_from_item(item):
"""
Get defendant/service for given item
"""
customer_id = None
item['rawItem'] = _get_deobfuscate_item(item['rawItem'])
try:
ip_addr, hostname, url = _get_item_ip_hostname_url(item)
if not ip_addr and not hostname:
raise BadRequest('Unable to get infos for this item')
except ValidationError:
raise BadRequest('Invalid item')
for param in {'urls': [url]}, {'ips': [ip_addr], 'fqdn': [hostname]}:
try:
services = ImplementationFactory.instance.get_singleton_of(
'CustomerDaoBase'
).get_services_from_items(**param)
schema.valid_adapter_response('CustomerDaoBase', 'get_services_from_items', services)
if services:
break
except (CustomerDaoException, schema.InvalidFormatError, schema.SchemaNotFound):
raise InternalServerError('Unknown exception while identifying defendant')
if services:
try:
customer_id = services[0]['defendant']['customerId']
service = services[0]['service']
except (IndexError, KeyError):
raise InternalServerError('Unable to parse CustomerDaoBase response')
if not customer_id:
raise NotFound('No defendant found for this item')
return {'customerId': customer_id, 'service': service}
def get_defendant_services(customer_id):
"""
Get services for a defendant
"""
try:
response = ImplementationFactory.instance.get_singleton_of(
'CustomerDaoBase'
).get_customer_services(customer_id)
schema.valid_adapter_response('CustomerDaoBase', 'get_customer_services', response)
except (CustomerDaoException, schema.InvalidFormatError, schema.SchemaNotFound) as ex:
return InternalServerError(str(ex))
return response
def test_aborter(self):
abort = exceptions.abort
self.assert_raises(exceptions.BadRequest, abort, 400)
self.assert_raises(exceptions.Unauthorized, abort, 401)
self.assert_raises(exceptions.Forbidden, abort, 403)
self.assert_raises(exceptions.NotFound, abort, 404)
self.assert_raises(exceptions.MethodNotAllowed, abort, 405, ['GET', 'HEAD'])
self.assert_raises(exceptions.NotAcceptable, abort, 406)
self.assert_raises(exceptions.RequestTimeout, abort, 408)
self.assert_raises(exceptions.Gone, abort, 410)
self.assert_raises(exceptions.LengthRequired, abort, 411)
self.assert_raises(exceptions.PreconditionFailed, abort, 412)
self.assert_raises(exceptions.RequestEntityTooLarge, abort, 413)
self.assert_raises(exceptions.RequestURITooLarge, abort, 414)
self.assert_raises(exceptions.UnsupportedMediaType, abort, 415)
self.assert_raises(exceptions.UnprocessableEntity, abort, 422)
self.assert_raises(exceptions.InternalServerError, abort, 500)
self.assert_raises(exceptions.NotImplemented, abort, 501)
self.assert_raises(exceptions.BadGateway, abort, 502)
self.assert_raises(exceptions.ServiceUnavailable, abort, 503)
myabort = exceptions.Aborter({1: exceptions.NotFound})
self.assert_raises(LookupError, myabort, 404)
self.assert_raises(exceptions.NotFound, myabort, 1)
myabort = exceptions.Aborter(extra={1: exceptions.NotFound})
self.assert_raises(exceptions.NotFound, myabort, 404)
self.assert_raises(exceptions.NotFound, myabort, 1)
def cute_board_spider():
"""
:function: cute_board_spider
??????????????
"""
try:
board_list = get_webview_board()
except:
raise InternalServerError()
webview_board.flushdb()
webview_board.set('webview_board_list', board_list)
webview_board.save()
# @celery.task(name='send_mail')
# def send_async_email(msg):
# """
# :function: send_mail
# :**kwargs:
# {'feedback': feedback, 'contact': contact}
#
# ???(ios????)
# """
# with app.app_context():
# mail.send(msg)
def make_response(self, data, *args, **kwargs):
"""Looks up the representation transformer for the requested media
type, invoking the transformer to create a response object. This
defaults to default_mediatype if no transformer is found for the
requested mediatype. If default_mediatype is None, a 406 Not
Acceptable response will be sent as per RFC 2616 section 14.1
:param data: Python object containing response data to be transformed
"""
default_mediatype = kwargs.pop('fallback_mediatype', None) or self.default_mediatype
mediatype = request.accept_mimetypes.best_match(
self.representations,
default=default_mediatype,
)
if mediatype is None:
raise NotAcceptable()
if mediatype in self.representations:
resp = self.representations[mediatype](data, *args, **kwargs)
resp.headers['Content-Type'] = mediatype
return resp
elif mediatype == 'text/plain':
resp = original_flask_make_response(str(data), *args, **kwargs)
resp.headers['Content-Type'] = 'text/plain'
return resp
else:
raise InternalServerError()
def patch_node(node_id):
# Parse the request
node_id = str2id(node_id)
patch = request.get_json()
# Find the node type.
node = mongo.find_one_or_404('nodes', node_id,
projection={'node_type': 1})
try:
node_type = node['node_type']
except KeyError:
msg = 'Node %s has no node_type property' % node_id
log.warning(msg)
raise wz_exceptions.InternalServerError(msg)
log.debug('User %s wants to PATCH %s node %s',
authentication.current_user_id(), node_type, node_id)
# Find the PATCH handler for the node type.
try:
patch_handler = custom.patch_handlers[node_type]
except KeyError:
log.info('No patch handler for node type %r', node_type)
raise wz_exceptions.MethodNotAllowed('PATCH on node type %r not allowed' % node_type)
# Let the PATCH handler do its thing.
return patch_handler(node_id, patch)
def edit_comment(user_id, node_id, patch):
"""Edits a single comment.
Doesn't do permission checking; users are allowed to edit their own
comment, and this is not something you want to revoke anyway. Admins
can edit all comments.
"""
# Find the node. We need to fetch some more info than we use here, so that
# we can pass this stuff to Eve's patch_internal; that way the validation &
# authorisation system has enough info to work.
nodes_coll = current_app.data.driver.db['nodes']
projection = {'user': 1,
'project': 1,
'node_type': 1}
node = nodes_coll.find_one(node_id, projection=projection)
if node is None:
log.warning('User %s wanted to patch non-existing node %s' % (user_id, node_id))
raise wz_exceptions.NotFound('Node %s not found' % node_id)
if node['user'] != user_id and not authorization.user_has_role('admin'):
raise wz_exceptions.Forbidden('You can only edit your own comments.')
# Use Eve to PATCH this node, as that also updates the etag.
r, _, _, status = current_app.patch_internal('nodes',
{'properties.content': patch['content'],
'project': node['project'],
'user': node['user'],
'node_type': node['node_type']},
concurrency_check=False,
_id=node_id)
if status != 200:
log.error('Error %i editing comment %s for user %s: %s',
status, node_id, user_id, r)
raise wz_exceptions.InternalServerError('Internal error %i from Eve' % status)
else:
log.info('User %s edited comment %s', user_id, node_id)
# Fetch the new content, so the client can show these without querying again.
node = nodes_coll.find_one(node_id, projection={'properties.content_html': 1})
return status, node
def generate_and_store_short_code(node):
nodes_coll = current_app.data.driver.db['nodes']
node_id = node['_id']
log.debug('Creating new short link for node %s', node_id)
max_attempts = 10
for attempt in range(1, max_attempts):
# Generate a new short code
short_code = create_short_code(node)
log.debug('Created short code for node %s: %s', node_id, short_code)
node['short_code'] = short_code
# Store it in MongoDB
try:
result = nodes_coll.update_one({'_id': node_id},
{'$set': {'short_code': short_code}})
break
except pymongo.errors.DuplicateKeyError:
log.info('Duplicate key while creating short code, retrying (attempt %i/%i)',
attempt, max_attempts)
pass
else:
log.error('Unable to find unique short code for node %s after %i attempts, failing!',
node_id, max_attempts)
raise wz_exceptions.InternalServerError('Unable to create unique short code for node %s' %
node_id)
# We were able to store a short code, now let's verify the result.
if result.matched_count != 1:
log.warning('Unable to update node %s with new short_links=%r', node_id, node['short_code'])
raise wz_exceptions.InternalServerError('Unable to update node %s with new short links' %
node_id)
return short_code
def abort_with_error(status):
"""Aborts with the given status, or 500 if the status doesn't indicate an error.
If the status is < 400, status 500 is used instead.
"""
abort(status if status // 100 >= 4 else 500)
raise wz_exceptions.InternalServerError('abort() should have aborted!')
def make_response(self, data, *args, **kwargs):
"""Looks up the representation transformer for the requested media
type, invoking the transformer to create a response object. This
defaults to default_mediatype if no transformer is found for the
requested mediatype. If default_mediatype is None, a 406 Not
Acceptable response will be sent as per RFC 2616 section 14.1
:param data: Python object containing response data to be transformed
"""
default_mediatype = kwargs.pop('fallback_mediatype', None) or self.default_mediatype
mediatype = request.accept_mimetypes.best_match(
self.representations,
default=default_mediatype,
)
if mediatype is None:
raise NotAcceptable()
if mediatype in self.representations:
resp = self.representations[mediatype](data, *args, **kwargs)
resp.headers['Content-Type'] = mediatype
return resp
elif mediatype == 'text/plain':
resp = original_flask_make_response(str(data), *args, **kwargs)
resp.headers['Content-Type'] = 'text/plain'
return resp
else:
raise InternalServerError()
def internal_server_error(e):
traceback.print_exception(e, e, None)
path = request.path
repo.create_issue('500 error at {path}\n {e}'.format(path=path, e=e), session.get('id', 'logged_out'), 'decksite', 'PennyDreadfulMTG/perf-reports')
view = InternalServerError(e)
return view.page(), 500
def make_response(self, data, *args, **kwargs):
"""Looks up the representation transformer for the requested media
type, invoking the transformer to create a response object. This
defaults to default_mediatype if no transformer is found for the
requested mediatype. If default_mediatype is None, a 406 Not
Acceptable response will be sent as per RFC 2616 section 14.1
:param data: Python object containing response data to be transformed
"""
default_mediatype = kwargs.pop('fallback_mediatype', None) or self.default_mediatype
mediatype = request.accept_mimetypes.best_match(
self.representations,
default=default_mediatype,
)
if mediatype is None:
raise NotAcceptable()
if mediatype in self.representations:
resp = self.representations[mediatype](data, *args, **kwargs)
resp.headers['Content-Type'] = mediatype
return resp
elif mediatype == 'text/plain':
resp = original_flask_make_response(str(data), *args, **kwargs)
resp.headers['Content-Type'] = 'text/plain'
return resp
else:
raise InternalServerError()
def create_app():
app = flask.Flask(__name__)
config_file = "./ctf.json"
if 'CTF_CONFIG' in os.environ:
config_file = os.environ['CTF_CONFIG']
try:
config = open(config_file, 'r')
app.config.update(json.load(config))
except IOError:
raise IOError("The CTF configuration file could not be found")
except ValueError:
raise ValueError("The CTF configuration file was malformed")
redis_url = app.config.get('REDIS_URL', 'redis://localhost')
app.redis = redis.StrictRedis.from_url(redis_url)
# Setup extensions
ext.db.init_app(app)
ext.csrf.init_app(app)
@app.before_first_request
def create_db():
db.create_all()
setup.build_challenges()
@app.context_processor
def inject_jinja_globals():
"""The authed flag should NOT be used to secure access control.
The aim of the 'authed' global is simply better link rendering in
templates.
"""
return {'authed': 'key' in flask.session,
'name': core.get_name()}
def handle_error(exc):
if not isinstance(exc, exceptions.HTTPException):
exc = exceptions.InternalServerError()
return flask.render_template('error.html', code=exc.code), exc.code
for code in exceptions.default_exceptions.keys():
app.register_error_handler(code, handle_error)
app.register_blueprint(frontend.bp)
app.register_blueprint(api.bp, url_prefix='/api')
return app
def create_blender_sync_node(project_id, admin_group_id, user_id):
"""Creates a node for Blender Sync, with explicit write access for the admin group.
Writes the node to the database.
:param project_id: ID of the home project
:type project_id: ObjectId
:param admin_group_id: ID of the admin group of the project. This group will
receive write access to the node.
:type admin_group_id: ObjectId
:param user_id: ID of the owner of the node.
:type user_id: ObjectId
:returns: The created node.
:rtype: dict
"""
log.debug('Creating sync node for project %s, user %s', project_id, user_id)
node = {
'project': ObjectId(project_id),
'node_type': 'group',
'name': SYNC_GROUP_NODE_NAME,
'user': ObjectId(user_id),
'description': SYNC_GROUP_NODE_DESC,
'properties': {'status': 'published'},
'permissions': {
'users': [],
'groups': [
{'group': ObjectId(admin_group_id),
'methods': ['GET', 'PUT', 'POST', 'DELETE']}
],
'world': [],
}
}
r, _, _, status = current_app.post_internal('nodes', node)
if status != 201:
log.warning('Unable to create Blender Sync node for home project %s: %s',
project_id, r)
raise wz_exceptions.InternalServerError('Unable to create Blender Sync node')
node.update(r)
return node
def create_file_doc_for_upload(project_id, uploaded_file):
"""Creates a secure filename and a document in MongoDB for the file.
The (project_id, filename) tuple should be unique. If such a document already
exists, it is updated with the new file.
:param uploaded_file: file from request.files['form-key']
:type uploaded_file: werkzeug.datastructures.FileStorage
:returns: a tuple (file_id, filename, status), where 'filename' is the internal
filename used on GCS.
"""
project_id = ObjectId(project_id)
# Hash the filename with path info to get the internal name. This should
# be unique for the project.
# internal_filename = uploaded_file.filename
_, ext = os.path.splitext(uploaded_file.filename)
internal_filename = uuid.uuid4().hex + ext
# For now, we don't support overwriting files, and create a new one every time.
# # See if we can find a pre-existing file doc.
# files = current_app.data.driver.db['files']
# file_doc = files.find_one({'project': project_id,
# 'name': internal_filename})
file_doc = None
# TODO: at some point do name-based and content-based content-type sniffing.
new_props = {'filename': uploaded_file.filename,
'content_type': uploaded_file.mimetype,
'length': uploaded_file.content_length,
'project': project_id,
'status': 'uploading'}
if file_doc is None:
# Create a file document on MongoDB for this file.
file_doc = create_file_doc(name=internal_filename, **new_props)
file_fields, _, _, status = current_app.post_internal('files', file_doc)
else:
file_doc.update(new_props)
file_fields, _, _, status = current_app.put_internal('files', remove_private_keys(file_doc))
if status not in (200, 201):
log.error('Unable to create new file document in MongoDB, status=%i: %s',
status, file_fields)
raise wz_exceptions.InternalServerError()
log.debug('Created file document %s for uploaded file %s; internal name %s',
file_fields['_id'], uploaded_file.filename, internal_filename)
return file_fields['_id'], internal_filename, status