You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

application.py 4.5 kB

5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. # Copyright 2019 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. """Web application module."""
  16. import os
  17. from importlib import import_module
  18. from werkzeug.datastructures import Headers
  19. from werkzeug.exceptions import HTTPException
  20. from flask import Flask
  21. from flask import request
  22. from flask import Response
  23. from flask_cors import CORS
  24. from mindinsight.conf import settings
  25. from mindinsight.utils.hook import HookUtils
  26. from mindinsight.datavisual.common.log import logger
  27. from mindinsight.datavisual.common.exceptions import RequestMethodNotAllowed
  28. from mindinsight.datavisual.common import error_handler
  29. from mindinsight.datavisual.utils.tools import find_app_package
  30. from mindinsight.datavisual.utils.tools import get_img_mimetype
  31. from mindinsight.utils.exceptions import MindInsightException
  32. def get_security_headers():
  33. """Get security headers."""
  34. domain_white_list = []
  35. for hook in HookUtils.instance().hooks():
  36. domain_white_list += hook.register_secure_domains()
  37. content_security_policy = {
  38. 'img-src': ["'self'", 'data:'],
  39. 'style-src': ["'self'", "'unsafe-inline'"],
  40. 'frame-src': ["'self'"] + domain_white_list,
  41. 'frame-ancestors': ["'self'"] + domain_white_list,
  42. 'default-src': ["'self'"],
  43. 'script-src': ["'self'", "'unsafe-eval'"]
  44. }
  45. headers = {
  46. 'X-Frame-Options': 'SAMEORIGIN',
  47. 'X-XSS-Protection': '1; mode=block',
  48. 'X-Content-Type-Options': 'nosniff',
  49. 'Access-Control-Allow-Methods': ', '.join(settings.SUPPORT_REQUEST_METHODS),
  50. 'Content-Security-Policy': '; '.join([
  51. f"{k} {' '.join(v)}" for k, v in content_security_policy.items()
  52. ]),
  53. 'X-Download-Options': 'noopen',
  54. 'Cache-Control': 'no-store',
  55. 'Pragma': 'no-cache'
  56. }
  57. return list(headers.items())
  58. SECURITY_HEADERS = get_security_headers()
  59. class CustomResponse(Response):
  60. """Define custom response."""
  61. def __init__(self, response=None, **kwargs):
  62. headers = kwargs.get("headers")
  63. if isinstance(response, bytes):
  64. mimetype = get_img_mimetype(response)
  65. SECURITY_HEADERS.append(('Content-Type', mimetype))
  66. if headers is None:
  67. headers = Headers(SECURITY_HEADERS)
  68. else:
  69. for header in SECURITY_HEADERS:
  70. headers.add(*header)
  71. kwargs['headers'] = headers
  72. super(CustomResponse, self).__init__(response, **kwargs)
  73. def _init_app_module(app):
  74. """
  75. Init app module.
  76. Args:
  77. app (Flask): An instance of Flask.
  78. """
  79. packages = find_app_package()
  80. for package in packages:
  81. try:
  82. app_module = import_module(package)
  83. app_module.init_module(app)
  84. except AttributeError:
  85. logger.debug('[%s].init_module not exists.', package)
  86. def before_request():
  87. """A function to run before each request."""
  88. if request.method not in settings.SUPPORT_REQUEST_METHODS:
  89. raise RequestMethodNotAllowed()
  90. def create_app():
  91. """Set flask APP config, and start the data manager."""
  92. static_url_path = settings.URL_PATH_PREFIX + "/static"
  93. static_folder_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'ui', 'dist', 'static'))
  94. app = Flask(__name__, static_url_path=static_url_path, static_folder=static_folder_path)
  95. if settings.ENABLE_CORS:
  96. CORS(app, supports_credentials=True)
  97. app.before_request(before_request)
  98. app.register_error_handler(HTTPException, error_handler.handle_http_exception_error)
  99. app.register_error_handler(MindInsightException, error_handler.handle_mindinsight_error)
  100. app.register_error_handler(Exception, error_handler.handle_unknown_error)
  101. app.response_class = CustomResponse
  102. _init_app_module(app)
  103. return app
  104. APP = create_app()