Commit d75da47f authored by Anton Akhmerov's avatar Anton Akhmerov
Browse files

Merge branch '509-solution-cache' into 'master'

Cache control for solution images

Closes #509

See merge request zesje/zesje!310
parents 1294c3e7 371e00ea
from flask import abort, Response, current_app
from flask import abort, Response, current_app, request
from pathlib import Path
from werkzeug.http import parse_date, http_date
from datetime import datetime
import cv2
import numpy as np
......@@ -60,6 +63,15 @@ def get(exam_id, problem_id, submission_id, full_page=False):
if len(pages) == 0:
abort(404, f'Page #{page_number} is missing for all copies of submission #{submission_id}.')
# Convert to int to match the time resolution of HTTP headers (seconds)
last_modified = int(max(Path(page.abs_path).stat().st_mtime for page in pages))
if modified_since := request.headers.get('If-Modified-Since'):
modified_since = parse_date(modified_since).timestamp()
if last_modified == modified_since:
# Send 304 Not Modified with empty body
return '', 304
solution = Solution.query.filter(Solution.submission_id ==,
Solution.problem_id == problem_id).one()
......@@ -118,7 +130,12 @@ def get(exam_id, problem_id, submission_id, full_page=False):
stitched_image = np.concatenate(tuple(resized_images), axis=0)
image_encoded = cv2.imencode(".jpg", stitched_image)[1].tostring()
return Response(image_encoded, 200, mimetype='image/jpeg')
headers = {
'Last-Modified': http_date(datetime.fromtimestamp(last_modified)),
'Cache-Control': 'no-cache'
return Response(image_encoded, 200, headers=headers, mimetype='image/jpeg')
def _grey_out_student_widget(page_im, coords, dpi):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment