mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
The mirror proxies /<origin>/<path> to https://<origin>/<path> and relayed the upstream Location header untouched. A root-relative Location then resolved against the mirror instead of the origin, the prefix that names the origin was lost, the follow-up request matched no location block and fell into the catch-all 404. Chromium discards a 404 served for a script request, so the page lost the asset with net::ERR_BLOCKED_BY_ORB. MIG job 105068912392 shows both halves, 28 times each: GET /unpkg.com/3d-force-graph/dist/3d-force-graph.min.js answered 302, then GET /3d-force-graph@1.80.0/dist/3d-force-graph.min.js answered 404. unpkg redirects an unversioned path to the resolved version and expresses the target as an absolute path. The forms move into a redirect_sources filter so the template states the intent once and the list is unit-tested. Measured against a two-container nginx fixture: an absolute https Location, an absolute http one and a root-relative one all come back as /<origin>/target. A Location naming a third host stays untouched, which is unchanged behaviour and still leaks past the mirror. A network-path form was written first and then dropped: nginx normalises such a target in return, and routing one through add_header emits two Location headers of which the proxy relays only the first, so the case could not be produced and the rule stayed unproven. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
43 lines
1.4 KiB
Django/Jinja
43 lines
1.4 KiB
Django/Jinja
{% set mirror_origin_hosts = lookup('applications') | external_asset_origins(None, DOMAIN_PRIMARY) %}
|
|
server
|
|
{
|
|
server_name {{ lookup('domain',application_id) }};
|
|
|
|
{% include 'roles/sys-front-tls/templates/nginx_ssl_header.j2' %}
|
|
|
|
{% include 'roles/sys-svc-proxy/templates/headers/content_security_policy.conf.j2' %}
|
|
|
|
{% set aca_origin = "* always" %}
|
|
{% include 'roles/sys-svc-proxy/templates/headers/access_control_allow.conf.j2' %}
|
|
|
|
charset utf-8;
|
|
|
|
{% for origin_host in mirror_origin_hosts %}
|
|
location /{{ origin_host }}/
|
|
{
|
|
resolver {{ NETWORK_PUBLIC_DNS_RESOLVERS | join(' ') }} ipv6={{ NETWORK_IPV6_ENABLED | on_off }} valid=300s;
|
|
set $mirror_upstream_{{ loop.index }} {{ origin_host }};
|
|
rewrite ^/{{ origin_host | replace('.', '\\.') }}/(.*)$ /$1 break;
|
|
proxy_pass https://$mirror_upstream_{{ loop.index }};
|
|
proxy_ssl_server_name on;
|
|
proxy_ssl_name {{ origin_host }};
|
|
proxy_set_header Host {{ origin_host }};
|
|
{% for redirect_source in origin_host | redirect_sources %}
|
|
proxy_redirect {{ redirect_source }} /{{ origin_host }}/;
|
|
{% endfor %}
|
|
proxy_cache cache;
|
|
proxy_cache_valid 200 301 302 168h;
|
|
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
|
|
proxy_ignore_headers Set-Cookie Cache-Control Expires;
|
|
proxy_hide_header Set-Cookie;
|
|
proxy_hide_header Access-Control-Allow-Origin;
|
|
expires 7d;
|
|
}
|
|
{% endfor %}
|
|
|
|
location /
|
|
{
|
|
return 404;
|
|
}
|
|
}
|