|
1 | | -import gzip |
2 | | -import logging |
3 | | -import time |
4 | | - |
5 | | -from flask_caching import Cache |
6 | | -from werkzeug.exceptions import HTTPException |
7 | | - |
8 | | -from flask import Flask |
9 | | -from flask import g |
10 | | -from flask import request |
11 | | - |
12 | | -from app import settings |
13 | | -from app.helpers.utils import make_error_msg |
14 | | - |
15 | | -logger = logging.getLogger(__name__) |
16 | | -route_logger = logging.getLogger('app.routes') |
17 | | - |
18 | | -# Standard Flask application initialisation |
19 | | - |
20 | | -app = Flask(__name__) |
21 | | -app.config.from_object(settings) |
22 | | - |
23 | | -cache = Cache(app) |
24 | | - |
25 | | - |
26 | | -# NOTE it is better to have this method registered first (before validate_origin) otherwise |
27 | | -# the route might not be logged if another method reject the request. |
28 | | -@app.before_request |
29 | | -def log_route(): |
30 | | - g.setdefault('request_started', time.time()) |
31 | | - route_logger.debug('%s %s', request.method, request.path) |
32 | | - |
33 | | - |
34 | | -# Add CORS Headers to all request |
35 | | -@app.after_request |
36 | | -def add_cors_header(response): |
37 | | - # Do not add CORS header to internal /checker endpoint. |
38 | | - if request.endpoint == 'checker': |
39 | | - return response |
40 | | - |
41 | | - response.headers['Access-Control-Allow-Methods'] = 'GET, HEAD, OPTIONS' |
42 | | - response.headers['Access-Control-Allow-Headers'] = '*' |
43 | | - response.headers['Access-Control-Allow-Origin'] = "*" |
44 | | - return response |
45 | | - |
46 | | - |
47 | | -# Add Cache-Control Headers to all request except for checker |
48 | | -@app.after_request |
49 | | -def add_cache_control_header(response): |
50 | | - # Do not add Cache-Control header to internal /checker endpoint. |
51 | | - if request.endpoint == 'checker': |
52 | | - return response |
53 | | - |
54 | | - # no cache on these 5xx errors, they are supposed to be temporary |
55 | | - if response.status_code in (502, 503, 504, 507): |
56 | | - response.headers['Cache-Control'] = 'no-cache' |
57 | | - # short cache duration for other 5xx errors |
58 | | - elif response.status_code >= 500: |
59 | | - response.headers['Cache-Control'] = 'public, max-age=10' |
60 | | - else: |
61 | | - response.headers['Cache-Control'] = settings.CACHE_CONTROL_HEADER |
62 | | - return response |
63 | | - |
64 | | - |
65 | | -@app.after_request |
66 | | -def compress(response): |
67 | | - accept_encoding = request.headers.get('accept-encoding', '').lower() |
68 | | - |
69 | | - if ( |
70 | | - response.status_code < 200 or response.status_code >= 300 or response.direct_passthrough or |
71 | | - 'gzip' not in accept_encoding or 'Content-Encoding' in response.headers |
72 | | - ): |
73 | | - return response |
74 | | - |
75 | | - content = gzip.compress(response.get_data(), compresslevel=settings.GZIP_COMPRESSION_LEVEL) |
76 | | - response.set_data(content) |
77 | | - response.headers['content-length'] = len(content) |
78 | | - response.headers['content-encoding'] = 'gzip' |
79 | | - return response |
80 | | - |
81 | | - |
82 | | -# NOTE it is better to have this method registered last (after add_cors_header) otherwise |
83 | | -# the response might not be correct (e.g. headers added in another after_request hook). |
84 | | -@app.after_request |
85 | | -def log_response(response): |
86 | | - log_extra = { |
87 | | - 'response': { |
88 | | - "status_code": response.status_code, |
89 | | - "headers": dict(response.headers.items()), |
90 | | - }, |
91 | | - "duration": time.time() - g.get('request_started', time.time()) |
92 | | - } |
93 | | - if route_logger.isEnabledFor(logging.DEBUG): |
94 | | - log_extra['response']['json'] = response.json if response.is_json else response.data |
95 | | - route_logger.info("%s %s - %s", request.method, request.path, response.status, extra=log_extra) |
96 | | - return response |
97 | | - |
98 | | - |
99 | | -# Register error handler to make sure that every error returns a json answer |
100 | | -@app.errorhandler(Exception) |
101 | | -def handle_exception(err): |
102 | | - """Return JSON instead of HTML for HTTP errors.""" |
103 | | - if isinstance(err, HTTPException): |
104 | | - if err.code >= 500: |
105 | | - logger.exception(err) |
106 | | - else: |
107 | | - logger.error(err) |
108 | | - return make_error_msg(err.code, err.description) |
109 | | - |
110 | | - logger.exception('Unexpected exception: %s', err) |
111 | | - return make_error_msg(500, "Internal server error, please consult logs") |
112 | | - |
113 | | - |
114 | | -@app.teardown_appcontext |
115 | | -def close_db_connection(exception): |
116 | | - if exception: |
117 | | - logger.exception('Unexpected exception: %s', exception) |
118 | | - # close db connection |
119 | | - if hasattr(g, 'db_connection'): |
120 | | - g.db_connection.close() |
121 | | - |
122 | | - |
123 | | -from app import routes # isort:skip pylint: disable=wrong-import-position |
| 1 | +from app import routes |
| 2 | +from app.app import app |
0 commit comments