using Invercargill; using Invercargill.DataStructures; using Inversion; using Astralis; namespace Statum { /** * `GET /_statum/resource/{name}` — serves precompressed {@link StatumResource}s. * * Mirrors the old Spry 0.1 `StaticResourceProvider` (removed in Spry * 0.2): all registered * {@link StatumResource}s are collected at construction, the `{name}` segment * selects one, the best encoding is chosen from `Accept-Encoding`, and * `ETag`/`If-None-Match` is honoured. */ public class ResourceEndpoint : Object, Endpoint { private Dictionary resource_map = inject_all().to_dictionary(r => r.name); public async HttpResult handle_request(HttpContext http_context, RouteContext route_context) throws GLib.Error { var name = route_context.mapped_parameters.get_or_default("name"); if (name == null) { return new HttpStringResult("No such resource.", StatusCode.NOT_FOUND); } StatumResource resource; if (!resource_map.try_get((!)name, out resource)) { return new HttpStringResult(@"No such resource \"$((!)name)\".", StatusCode.NOT_FOUND); } var accepts = new HashSet(); foreach (var header in http_context.request.headers.get_or_empty("Accept-Encoding")) { foreach (var token in header.split(",")) { var encoding = token.strip(); if (encoding.length > 0) { accepts.add(encoding); } } } var best = resource.get_best_encoding(accepts); var etag = resource.get_etag_for(best); foreach (var header in http_context.request.headers.get_or_empty("If-None-Match")) { if (header.contains(etag)) { return new HttpEmptyResult(StatusCode.NOT_MODIFIED); } } return resource.to_result(best); } } }