|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
| 5 | +from datetime import timedelta |
| 6 | +from email.utils import parsedate_to_datetime |
5 | 7 | from unittest.mock import patch |
6 | 8 | from urllib.parse import parse_qs, urlparse |
7 | 9 | from uuid import uuid4 |
|
10 | 12 | from httpx import AsyncClient |
11 | 13 | from jinja2 import Environment, PackageLoader, select_autoescape |
12 | 14 | from lsst.daf.butler import LabeledButlerFactory |
| 15 | +from safir.datetime import current_datetime |
13 | 16 |
|
14 | 17 | from datalinker.config import config |
15 | 18 |
|
@@ -194,13 +197,19 @@ async def test_links(client: AsyncClient, mock_butler: MockButler) -> None: |
194 | 197 | f"https://presigned-url.example.com/{mock_butler.uuid!s}" |
195 | 198 | "?X-Amz-Signature=abcdef" |
196 | 199 | ) |
| 200 | + expected_expires = current_datetime() + config.links_lifetime |
197 | 201 |
|
198 | 202 | # Use iD to test the IVOA requirement of case insensitive parameters. |
199 | 203 | r = await client.get( |
200 | 204 | "/api/datalink/links", |
201 | 205 | params={"iD": f"butler://label-http/{mock_butler.uuid!s}"}, |
202 | 206 | ) |
203 | 207 | assert r.status_code == 200 |
| 208 | + expires = parsedate_to_datetime(r.headers["Expires"]) |
| 209 | + assert expected_expires <= expires |
| 210 | + assert expires <= expected_expires + timedelta(seconds=5) |
| 211 | + lifetime = int(config.links_lifetime.total_seconds()) |
| 212 | + assert r.headers["Cache-Control"] == f"max-age={lifetime}" |
204 | 213 |
|
205 | 214 | # The URL is already signed, so it should be passed through unchanged |
206 | 215 | env = Environment( |
|
0 commit comments