Manual static folder
このコミットが含まれているのは:
コミット
90e1e2099a
|
@ -12,7 +12,7 @@ from anonstream.quart import Quart
|
||||||
compress = Compress()
|
compress = Compress()
|
||||||
|
|
||||||
def create_app(toml_config):
|
def create_app(toml_config):
|
||||||
app = Quart('anonstream')
|
app = Quart('anonstream', static_folder=None)
|
||||||
app.jinja_options['trim_blocks'] = True
|
app.jinja_options['trim_blocks'] = True
|
||||||
app.jinja_options['lstrip_blocks'] = True
|
app.jinja_options['lstrip_blocks'] = True
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,18 @@
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from quart import current_app, request, render_template, abort, make_response, redirect, url_for, abort
|
from quart import current_app, request, render_template, abort, make_response, redirect, url_for, abort, send_from_directory
|
||||||
from werkzeug.exceptions import TooManyRequests
|
from werkzeug.exceptions import TooManyRequests
|
||||||
|
|
||||||
from anonstream.captcha import get_captcha_image
|
from anonstream.captcha import get_captcha_image
|
||||||
from anonstream.segments import segments, StopSendingSegments
|
from anonstream.segments import segments, StopSendingSegments
|
||||||
from anonstream.stream import is_online, get_stream_uptime
|
from anonstream.stream import is_online, get_stream_uptime
|
||||||
from anonstream.user import watching, create_eyes, renew_eyes, EyesException, RatelimitedEyes
|
from anonstream.user import watching, create_eyes, renew_eyes, EyesException, RatelimitedEyes
|
||||||
from anonstream.routes.wrappers import with_user_from, auth_required
|
from anonstream.routes.wrappers import with_user_from, auth_required, clean_cache_headers
|
||||||
from anonstream.utils.security import generate_csp
|
from anonstream.utils.security import generate_csp
|
||||||
|
|
||||||
|
STATIC_DIRECTORY = current_app.root_path / 'static'
|
||||||
|
|
||||||
@current_app.route('/')
|
@current_app.route('/')
|
||||||
@with_user_from(request)
|
@with_user_from(request)
|
||||||
async def home(user):
|
async def home(user):
|
||||||
|
@ -64,3 +66,9 @@ async def captcha(user):
|
||||||
return abort(410)
|
return abort(410)
|
||||||
else:
|
else:
|
||||||
return image, {'Content-Type': 'image/jpeg'}
|
return image, {'Content-Type': 'image/jpeg'}
|
||||||
|
|
||||||
|
@current_app.route('/static/<filename>')
|
||||||
|
@with_user_from(request)
|
||||||
|
@clean_cache_headers
|
||||||
|
async def static(user, filename):
|
||||||
|
return await send_from_directory(STATIC_DIRECTORY, filename)
|
||||||
|
|
|
@ -127,3 +127,28 @@ async def render_template_with_etag(template, deferred_kwargs, **kwargs):
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
return rendered_template, {'ETag': etag}
|
return rendered_template, {'ETag': etag}
|
||||||
|
|
||||||
|
def clean_cache_headers(f):
|
||||||
|
@wraps(f)
|
||||||
|
async def wrapper(*args, **kwargs):
|
||||||
|
response = await f(*args, **kwargs)
|
||||||
|
|
||||||
|
# Remove Last-Modified
|
||||||
|
try:
|
||||||
|
response.headers.pop('Last-Modified')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Obfuscate ETag
|
||||||
|
try:
|
||||||
|
original_etag = response.headers['ETag']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
parts = CONFIG['SECRET_KEY'] + b'etag\0' + original_etag.encode()
|
||||||
|
tag = hashlib.sha256(parts).hexdigest()
|
||||||
|
response.headers['ETag'] = f'"{tag}"'
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
読み込み中…
新しいイシューから参照