| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- using Invercargill;
- using Invercargill.DataStructures;
- using Astralis;
- namespace Statum {
- /**
- * Base class for pre-rendered Statum pages.
- *
- * A page is a static, precompressed document served at its route. Build-time
- * composition (templates/fragments, `pstm-res` rewriting) aside, it is just a
- * precompressed resource — so a generated subclass (emitted by
- * `statum-mkpstm`) provides the precompressed byte arrays and the
- * encoding/ETag accessors, and this base does lean `Accept-Encoding`
- * negotiation, `ETag`/`If-None-Match` handling and serving.
- *
- * No slots are resolved: pages are loaded by browser navigations, which carry
- * no `X-Statum-Slot` headers, so the page endpoint stays as fast as possible.
- */
- public abstract class StatumPage : Object, Endpoint {
- /** Content type of the served page (normally `text/html`). */
- public abstract string content_type { get; }
- /** Best supported encoding from the encodings this page carries. */
- public abstract string get_best_encoding(Set<string> supported);
- /** The bytes for `encoding`. */
- public abstract unowned uint8[] get_encoding(string encoding);
- /** The ETag for `encoding`. */
- public abstract string get_etag_for(string encoding);
- public async HttpResult handle_request(HttpContext http_context, RouteContext route_context) throws GLib.Error {
- var best = get_best_encoding(parse_accept_encoding(http_context));
- var etag = get_etag_for(best);
- if (etag_matches(http_context, etag)) {
- return new HttpEmptyResult(StatusCode.NOT_MODIFIED);
- }
- var result = new HttpDataResult(Wrap.byte_array(get_encoding(best)));
- result.set_header("Content-Type", content_type);
- result.set_header("Content-Encoding", best);
- result.set_header("ETag", etag);
- return result;
- }
- private static Set<string> parse_accept_encoding(HttpContext http_context) {
- var supported = new HashSet<string>();
- 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) {
- supported.add(encoding);
- }
- }
- }
- return supported;
- }
- private static bool etag_matches(HttpContext http_context, string etag) {
- foreach (var header in http_context.request.headers.get_or_empty("If-None-Match")) {
- if (header.contains(etag)) {
- return true;
- }
- }
- return false;
- }
- }
- }
|