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.9 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # Copyright 2019-2021 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. from mindinsight.utils.log import setup_logger
  33. def get_security_headers():
  34. """Get security headers."""
  35. domain_white_list = []
  36. for hook in HookUtils.instance().hooks():
  37. domain_white_list += hook.register_secure_domains()
  38. content_security_policy = {
  39. 'img-src': ["'self'", 'data:'],
  40. 'style-src': ["'self'", "'unsafe-inline'"],
  41. 'frame-src': ["'self'"] + domain_white_list,
  42. 'frame-ancestors': ["'self'"] + domain_white_list,
  43. 'default-src': ["'self'"],
  44. 'script-src': ["'self'", "'unsafe-eval'"]
  45. }
  46. headers = {
  47. 'X-Frame-Options': 'SAMEORIGIN',
  48. 'X-XSS-Protection': '1; mode=block',
  49. 'X-Content-Type-Options': 'nosniff',
  50. 'Access-Control-Allow-Methods': ', '.join(settings.SUPPORT_REQUEST_METHODS),
  51. 'Content-Security-Policy': '; '.join([
  52. f"{k} {' '.join(v)}" for k, v in content_security_policy.items()
  53. ]),
  54. 'X-Download-Options': 'noopen',
  55. 'Cache-Control': 'no-store',
  56. 'Pragma': 'no-cache'
  57. }
  58. return list(headers.items())
  59. SECURITY_HEADERS = get_security_headers()
  60. class CustomResponse(Response):
  61. """Define custom response."""
  62. def __init__(self, response=None, **kwargs):
  63. headers = kwargs.get("headers")
  64. security_headers = list(SECURITY_HEADERS)
  65. if isinstance(response, bytes):
  66. mimetype = get_img_mimetype(response)
  67. security_headers.append(('Content-Type', mimetype))
  68. if headers is None:
  69. headers = Headers(security_headers)
  70. else:
  71. for header in security_headers:
  72. headers.add(*header)
  73. kwargs['headers'] = headers
  74. super(CustomResponse, self).__init__(response, **kwargs)
  75. def _init_app_module(app):
  76. """
  77. Init app module.
  78. Args:
  79. app (Flask): An instance of Flask.
  80. """
  81. packages = find_app_package()
  82. gunicorn_logger = setup_logger("gunicorn", "error")
  83. for package in packages:
  84. try:
  85. app_module = import_module(package)
  86. gunicorn_logger.info("[%s].init_module starts.", package)
  87. app_module.init_module(app)
  88. gunicorn_logger.info("[%s].init_module ends.", package)
  89. except AttributeError:
  90. logger.debug('[%s].init_module not exists.', package)
  91. def before_request():
  92. """A function to run before each request."""
  93. if request.method not in settings.SUPPORT_REQUEST_METHODS:
  94. raise RequestMethodNotAllowed()
  95. def create_app():
  96. """Set flask APP config, and start the data manager."""
  97. gunicorn_logger = setup_logger("gunicorn", "error")
  98. gunicorn_logger.info("create_app starts.")
  99. static_url_path = settings.URL_PATH_PREFIX + "/static"
  100. static_folder_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'ui', 'dist', 'static'))
  101. app = Flask(__name__, static_url_path=static_url_path, static_folder=static_folder_path)
  102. app.config['JSON_SORT_KEYS'] = False
  103. if settings.ENABLE_CORS:
  104. CORS(app, supports_credentials=True)
  105. app.before_request(before_request)
  106. app.register_error_handler(HTTPException, error_handler.handle_http_exception_error)
  107. app.register_error_handler(MindInsightException, error_handler.handle_mindinsight_error)
  108. app.register_error_handler(Exception, error_handler.handle_unknown_error)
  109. app.response_class = CustomResponse
  110. _init_app_module(app)
  111. gunicorn_logger.info("create_app ends.")
  112. return app
  113. APP = create_app()