Files
hassio-addons/seerr/rootfs/etc
Alexandre 5eb7cd2744 fix(seerr): re-encode ingress query strings for the OpenAPI validator (#2917)
* fix(seerr): re-encode ingress query strings for the OpenAPI validator

Searches through ingress fail with a 400 from the Seerr API, which the UI
reports as "500 Internal Server Error". The same searches succeed on the
directly published port 5055.

Supervisor proxies ingress traffic with `params=request.query`
(supervisor/api/ingress.py) - an already-decoded MultiDict - so aiohttp/yarl
re-encodes the query string on the way to the add-on. yarl's safe set is far
wider than the one express-openapi-validator accepts: it emits a space as "+"
and forwards ":", "/", "@", "!", "$", "'", "(", ")", "*" and "," bare, while
the validator tests the raw, still-encoded value against

    RESERVED_CHARS = /[\:\/\?#\[\]@!\$&\'()\*\+,;=]/

and rejects the request. That breaks most real titles - "Monsters, Inc.",
"Ocean's Eleven", "Mission: Impossible", "Mamma Mia!".

An njs handler now re-encodes exactly those characters before proxying. This
is lossless: yarl only emits them bare when they were literal characters of
the value, since anything ambiguous arrives already encoded ("+" as %2B, "&"
as %26, "=" as %3D). "&" and "=" are left alone as the query string's own
separators, and the path is forwarded byte-for-byte.

Verified against a real express-openapi-validator over all 19 characters in
RESERVED_CHARS, and diffed byte-for-byte against the previous config across
representative traffic: only query-string encoding changes.

Fixes #2906
Fixes #2646

* fix(seerr): ship the njs load_module snippet and encode "?" and ";"

Addresses two review findings.

1. The njs module never loaded. .templates/ha_automatic_packages.sh moves the
   rootfs /etc/nginx aside to /etc/nginx2 before installing nginx, then does
   `rm -r /etc/nginx` and restores the saved tree. That deletes the
   load_module snippet nginx-mod-http-js installs, so nginx aborted with
   `unknown directive "js_import"` and the service's finish hook would have
   shut the add-on down - all ingress dead, not just search. The image build
   still passed CI because it never starts nginx. The snippet now ships in the
   rootfs so it survives the swap, under the package's own filename so the two
   can never both be present and double-load the module.

2. "?" arrives bare from yarl and was not encoded. It slipped through testing
   because the validator strips one occurrence with `qs.replace('?', '')`
   before checking, so a single "?" passes by accident and only a second one
   ("Who? What?") returned 400.

NEEDS_ENCODING is now derived from the validator's RESERVED_CHARS minus the
"&" and "=" separators, rather than from the characters yarl happens to emit
bare today, so it stays correct if either side changes its safe set. The added
characters are a no-op for current traffic: yarl already percent-encodes
"# [ ] ;", so Seerr receives them encoded regardless.

Verified by replaying the build-time /etc/nginx2 swap and starting nginx, which
fails without the snippet and serves correctly with it; by sending every
RESERVED_CHAR bare; and by diffing forwarded bytes against master, unchanged at
2/20 with all query-parser edge cases identical.

* style(seerr): satisfy Codacy - double quotes in njs, changelog blank lines

Clears the 11 new Info-level Codacy findings: 9x ESLint 'quotes' in
njs/ingress.js and 2x markdownlint MD022/MD032 on the changelog entry.
No behaviour change; re-verified through the build-time /etc/nginx2 swap.
2026-07-28 09:13:31 +02:00
..
2026-02-20 10:52:15 +01:00