feat(truocloud): add TruoCloud provider - #197
Conversation
TruoCloud serves images from `https://img.truo.cloud/i/<pid>/<path>`, with the transformation as query parameters. Two modes share the path: a path mapped onto the tenant's own origin, and `/fetch/<encoded url>` to proxy a third-party one — the same shape as imgix's Web Folder and Web Proxy. Detection is by domain rather than path: `/i/` is far too generic for the shared path registry and would claim URLs that are not ours. A custom domain therefore needs an explicit provider, as with the other providers that allow them. Two details that are not obvious from the URL shape: - parameters are emitted sorted by name. The service accepts any order, but every builder of this contract sorts them, and two orderings of one request are two CDN cache entries for the same image. - commas stay literal. The transformation engine does not decode `%2C`, so an escaped `crop=60,30,0,0` is ignored and the image comes back uncropped, with a 200. `extract` drops `s` and `exp` instead of returning them as operations: they are an HMAC over that exact path and query, so carrying them through `generate` would produce a URL whose signature no longer covers it.
|
The red Diagnosis: That is why earlier fork PRs were green and this one is red: back then Reproduced against Two options, whichever you prefer: I add the one-character fix to this branch |
Adds a provider for TruoCloud image delivery.
URLs look like
https://img.truo.cloud/i/<pid>/<path>?w=800&f=auto, with thetransformation as query parameters. Two modes share the path — a path mapped
onto the tenant's own origin, and
/fetch/<encoded url>to proxy a third-partyone — the same shape as imgix's Web Folder and Web Proxy.
Follows
CONTRIBUTING.md: provider, test,data/domains.json,deno.jsonc,demo/src/examples.json, and the four registration points insrc/. Purelyadditive, no existing file loses a line.
Detection is by domain, not by path
/i/is far too generic for the shared path registry and would claim URLs thatare not ours, so it is registered in
domains.jsononly. A custom domaintherefore needs an explicit provider, the same as the other providers that
allow them.
Two things that are not obvious from the URL shape
Parameters come out sorted by name. The service accepts any order, but
every builder of this contract sorts them, and two orderings of one request are
two CDN cache entries for the same image.
Commas stay literal. The transformation engine does not decode
%2C, so anescaped
crop=60,30,0,0is ignored — the image comes back uncropped, with a200.
sortSearchundoes the escaping thatURLSearchParamsapplies.extractdropssandexpThey are an HMAC over that exact path and query. Returning them as operations
would let
generateproduce a URL carrying a signature that no longer coversit — a 403 at display time with nothing pointing at the cause.
Verified
deno test src/— 88 passed, 288 stepsdeno lintanddeno fmt --checkclean on the new filesthe service itself, which is how the TypeScript, PHP and server-side builders
of this contract are kept byte-identical
The demo example URL is live.