1
0
Fork 0
mirror of https://gitlab.com/SIGBUS/nyaa.git synced 2024-06-17 19:53:11 +00:00
nyaa/nyaa/__init__.py
Nicolas F 80c9d580eb Improve cache configuration (#564)
The Flask-Caching cache can now properly be configured from the
config.py, and redis caching has experimentally been tested and
confirmed to be working in theory.

We also document that one may want to use CACHE_THRESHOLD to limit
the maximum number of items in the simple cache.
2019-08-10 18:53:57 -07:00

132 lines
4.8 KiB
Python

import logging
import os
import string
import flask
from flask_assets import Bundle # noqa F401
from nyaa.api_handler import api_blueprint
from nyaa.extensions import assets, cache, db, fix_paginate, toolbar
from nyaa.template_utils import bp as template_utils_bp
from nyaa.template_utils import caching_url_for
from nyaa.utils import random_string
from nyaa.views import register_views
# Replace the Flask url_for with our cached version, since there's no real harm in doing so
# (caching_url_for has stored a reference to the OG url_for, so we won't recurse)
# Touching globals like this is a bit dirty, but nicer than replacing every url_for usage
flask.url_for = caching_url_for
def create_app(config):
""" Nyaa app factory """
app = flask.Flask(__name__)
app.config.from_object(config)
# Don't refresh cookie each request
app.config['SESSION_REFRESH_EACH_REQUEST'] = False
# Debugging
if app.config['DEBUG']:
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
toolbar.init_app(app)
app.logger.setLevel(logging.DEBUG)
# Forbid caching
@app.after_request
def forbid_cache(request):
request.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate, max-age=0'
request.headers['Pragma'] = 'no-cache'
request.headers['Expires'] = '0'
return request
# Add a timer header to the requests when debugging
# This gives us a simple way to benchmark requests off-app
import time
@app.before_request
def timer_before_request():
flask.g.request_start_time = time.time()
@app.after_request
def timer_after_request(request):
request.headers['X-Timer'] = time.time() - flask.g.request_start_time
return request
else:
app.logger.setLevel(logging.WARNING)
# Logging
if 'LOG_FILE' in app.config:
from logging.handlers import RotatingFileHandler
app.log_handler = RotatingFileHandler(
app.config['LOG_FILE'], maxBytes=10000, backupCount=1)
app.logger.addHandler(app.log_handler)
# Log errors and display a message to the user in production mdode
if not app.config['DEBUG']:
@app.errorhandler(500)
def internal_error(exception):
random_id = random_string(8, string.ascii_uppercase + string.digits)
# Pst. Not actually unique, but don't tell anyone!
app.logger.error('Exception occurred! Unique ID: %s', random_id, exc_info=exception)
markup_source = ' '.join([
'<strong>An error occurred!</strong>',
'Debug information has been logged.',
'Please pass along this ID: <kbd>{}</kbd>'.format(random_id)
])
flask.flash(flask.Markup(markup_source), 'danger')
return flask.redirect(flask.url_for('main.home'))
# Get git commit hash
app.config['COMMIT_HASH'] = None
master_head = os.path.abspath(os.path.join(os.path.dirname(__file__),
'../.git/refs/heads/master'))
if os.path.isfile(master_head):
with open(master_head, 'r') as head:
app.config['COMMIT_HASH'] = head.readline().strip()
# Enable the jinja2 do extension.
app.jinja_env.add_extension('jinja2.ext.do')
app.jinja_env.lstrip_blocks = True
app.jinja_env.trim_blocks = True
# The default jinja_env has the OG Flask url_for (from before we replaced it),
# so update the globals with our version
app.jinja_env.globals['url_for'] = flask.url_for
# Database
fix_paginate() # This has to be before the database is initialized
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['MYSQL_DATABASE_CHARSET'] = 'utf8mb4'
db.init_app(app)
# Assets
assets.init_app(app)
assets._named_bundles = {} # Hack to fix state carrying over in tests
main_js = Bundle('js/main.js', filters='rjsmin', output='js/main.min.js')
bs_js = Bundle('js/bootstrap-select.js', filters='rjsmin',
output='js/bootstrap-select.min.js')
assets.register('main_js', main_js)
assets.register('bs_js', bs_js)
# css = Bundle('style.scss', filters='libsass',
# output='style.css', depends='**/*.scss')
# assets.register('style_all', css)
# Blueprints
app.register_blueprint(template_utils_bp)
app.register_blueprint(api_blueprint)
register_views(app)
# Pregenerate some URLs to avoid repeat url_for calls
if 'SERVER_NAME' in app.config and app.config['SERVER_NAME']:
with app.app_context():
url = flask.url_for('static', filename='img/avatar/default.png', _external=True)
app.config['DEFAULT_GRAVATAR_URL'] = url
# Cache
cache.init_app(app, config=app.config)
return app