Merge pull request #932 from dalf/static-file-hash

static files: add a hash as a query
This commit is contained in:
Alexandre Flament 2022-03-05 12:03:44 +01:00 committed by GitHub
commit 740e3bc90f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 16 deletions

View file

@ -44,9 +44,9 @@ logto = /var/log/uwsgi/uwsgi.log
add-header = Connection: close add-header = Connection: close
# uwsgi serves the static files # uwsgi serves the static files
# expires set to one day as Flask does # expires set to one year since there are hashes
static-map = /static=/usr/local/searxng/searx/static static-map = /static=/usr/local/searxng/searx/static
static-expires = /* 864000 static-expires = /* 31557600
static-gzip-all = True static-gzip-all = True
offload-threads = %k offload-threads = %k

View file

@ -16,7 +16,7 @@ from timeit import default_timer
from html import escape from html import escape
from io import StringIO from io import StringIO
import typing import typing
from typing import List, Dict, Iterable from typing import List, Dict, Iterable, Optional
import urllib import urllib
import urllib.parse import urllib.parse
@ -348,7 +348,7 @@ def code_highlighter(codelines, language=None):
return html_code return html_code
def get_current_theme_name(override: str = None) -> str: def get_current_theme_name(override: Optional[str] = None) -> str:
"""Returns theme name. """Returns theme name.
Checks in this order: Checks in this order:
@ -373,14 +373,16 @@ def get_result_template(theme_name: str, template_name: str):
return 'result_templates/' + template_name return 'result_templates/' + template_name
def url_for_theme(endpoint: str, override_theme: str = None, **values): def url_for_theme(endpoint: str, override_theme: Optional[str] = None, **values):
suffix = ""
if endpoint == 'static' and values.get('filename'): if endpoint == 'static' and values.get('filename'):
theme_name = get_current_theme_name(override=override_theme) theme_name = get_current_theme_name(override=override_theme)
filename_with_theme = "themes/{}/{}".format(theme_name, values['filename']) filename_with_theme = "themes/{}/{}".format(theme_name, values['filename'])
if filename_with_theme in static_files: file_hash = static_files.get(filename_with_theme)
if file_hash:
values['filename'] = filename_with_theme values['filename'] = filename_with_theme
url = url_for(endpoint, **values) suffix = "?" + file_hash
return url return url_for(endpoint, **values) + suffix
def proxify(url: str): def proxify(url: str):

View file

@ -1,12 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import pathlib
import csv import csv
import hashlib import hashlib
import hmac import hmac
import re import re
import inspect import inspect
import itertools import itertools
from typing import Iterable, List, Tuple from typing import Iterable, List, Tuple, Dict
from io import StringIO from io import StringIO
from codecs import getincrementalencoder from codecs import getincrementalencoder
@ -58,13 +59,29 @@ def get_themes(templates_path):
return themes return themes
def get_static_files(static_path): def get_hash_for_file(file: pathlib.Path) -> str:
static_files = set() m = hashlib.sha1()
static_path_length = len(static_path) + 1 with file.open('rb') as f:
for directory, _, files in os.walk(static_path): m.update(f.read())
for filename in files: return m.hexdigest()
f = os.path.join(directory[static_path_length:], filename)
static_files.add(f)
def get_static_files(static_path: str) -> Dict[str, str]:
static_files: Dict[str, str] = {}
static_path_path = pathlib.Path(static_path)
def walk(path: pathlib.Path):
for file in path.iterdir():
if file.name.startswith('.'):
# ignore hidden file
continue
if file.is_file():
static_files[str(file.relative_to(static_path_path))] = get_hash_for_file(file)
if file.is_dir() and file.name not in ('node_modules', 'src'):
# ignore "src" and "node_modules" directories
walk(file)
walk(static_path_path)
return static_files return static_files

View file

@ -23,6 +23,11 @@ class ViewsTestCase(SearxTestCase):
webapp.app.config['TESTING'] = True # to get better error messages webapp.app.config['TESTING'] = True # to get better error messages
self.app = webapp.app.test_client() self.app = webapp.app.test_client()
# remove sha for the static file
# so the tests don't have to care about the changing URLs
for k in webapp.static_files:
webapp.static_files[k] = None
# set some defaults # set some defaults
test_results = [ test_results = [
{ {