From 1cb610988f159b9c28a45f84a4678ec2e66481c8 Mon Sep 17 00:00:00 2001 From: Swrup Date: Sat, 27 Sep 2025 18:49:16 +0200 Subject: [PATCH] ~ assets --- src/assets.ml | 41 +++++++++++++++++++++++------------------ src/config.ml | 2 ++ src/mte.ml | 27 +++++++++++++-------------- src/util.ml | 2 +- 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/assets.ml b/src/assets.ml index 50dc56bb..6b09c6c5 100644 --- a/src/assets.ml +++ b/src/assets.ml @@ -9,7 +9,22 @@ https://docs.taler.net/manpages/taler-exchange.conf.5.html https://docs.taler.net/design-documents/003-tos-rendering.html *) -type kind = Terms | Privacy +(* todo: maybe move this type to config.ml *) +type t = Terms | Privacy + +let etag = function + | Terms -> Config.terms_etag + | Privacy -> Config.privacy_etag + +let legal_version = function + | Terms -> Config.terms_legal_version + | Privacy -> Config.privacy_legal_version + +let base_dir = function + | Terms -> Config.terms_dir + | Privacy -> Config.privacy_dir + +let path ~lang ~ext t = Fpath.((base_dir t / lang / etag t) + ext) (* TODO better use of Fmt to have error prefix or smthing @@ -22,13 +37,9 @@ let supported_lang_arr, supported_ext_arr = | Error (`Msg e) -> Fmt.failwith "%s" e | Ok x -> x in - let aux kind = - let base_dir = - match kind with - | Terms -> Config.terms_dir - | Privacy -> Config.privacy_dir - in - let path_l = path_l |> List.filter_map (Fpath.rem_prefix base_dir) in + let aux t = + let prefix = base_dir t in + let path_l = path_l |> List.filter_map (Fpath.rem_prefix prefix) in let ext_l = path_l |> List.map Fpath.get_ext |> List.sort_uniq String.compare in @@ -87,14 +98,8 @@ let supported_lang_arr, supported_ext_arr = let is_supported_lang lang = Array.mem lang supported_lang_arr let is_supported_ext ext = Array.mem ext supported_ext_arr -let get_content ~lang ~ext kind = - let path = - let open Config in - match kind with - | Terms -> Fpath.((terms_dir / lang / terms_etag) + ext) - | Privacy -> Fpath.((privacy_dir / lang / privacy_etag) + ext) - in - let path_str = Fpath.to_string path in - match Assets_crunch.read path_str with - | None -> Fmt.error "static file not found: `%s`" path_str +let get_content ~lang ~ext t = + let path = Fpath.to_string (path ~lang ~ext t) in + match Assets_crunch.read path with + | None -> Fmt.error "static file not found: `%s`" path | Some data -> Ok data diff --git a/src/config.ml b/src/config.ml index 611537d7..3a153c66 100644 --- a/src/config.ml +++ b/src/config.ml @@ -11,3 +11,5 @@ let privacy_dir = Fpath.(v "privacy") (* ETAG is used as filename *) let terms_etag = "0" let privacy_etag = "0" +let terms_legal_version = "1" +let privacy_legal_version = "1" diff --git a/src/mte.ml b/src/mte.ml index 197b70f7..e99bcdba 100644 --- a/src/mte.ml +++ b/src/mte.ml @@ -57,34 +57,31 @@ module Static = struct (* - try to find a response with an acceptable mime-type, - then pick the version in the most preferred language of the user, - and finally apply compression if that is allowed by the client + - set ETAG header TODO: - - set an ETAG, - subsequent requests of the client should provide the tag in an "If-None-Match" header - to detect if the terms of service have changed. - - If not, a "304 Not Modified" response will be returned. - Note that the “304 Not Modified” will also be returned if the client changed - the "Accept-Language" or "Accept-Encoding" header. - - The ETAG is encoded in Crockford base-32. - - A "Taler-Terms-Version" header is generated to indicate the legal version of the terms. + to detect if the terms of service have changed + - If it did not change, a "304 Not Modified" response will be returned + - The ETAG is encoded in Crockford base-32 + - A "Taler-Terms-Version" header is generated to indicate the legal version of the terms - When returning a full response (not a “304 Not Modified”), the server should also include a “Avail-Languages” header which includes a comma-separated list of the languages in which the terms of service are available in *) - (* accept_ext_l and accept_lang_l are assumed to be sorted by preference *) let select_file headers kind = let open Syntax in - let accept_ext_l = Header_util.parse_accept_header headers in - let accept_lang_l = Header_util.parse_accept_language_header headers in let* ext = - accept_ext_l + headers + |> Header_util.parse_accept_header |> List.find_opt Assets.is_supported_ext |> Option.to_result ~none:"no acceptable mimetype" in let* lang = - accept_lang_l + headers + |> Header_util.parse_accept_language_header |> List.find_opt Assets.is_supported_lang |> Option.to_result ~none:"no acceptable language" in @@ -96,6 +93,7 @@ module Static = struct let static kind req _server _env = let open Vif.Response.Syntax in let headers = Vif.Request.headers req in + let _if_none_match = Vif.Headers.get headers "if-none-match" in let data = match select_file headers kind with | Error e -> Fmt.failwith "%s" e @@ -103,8 +101,9 @@ module Static = struct in let compression = Header_util.select_encoding headers in let* () = Vif.Response.with_string ?compression req data in - let field = "content-type" in - let* () = Vif.Response.add ~field "html; charset=utf-8" in + let* () = Vif.Response.add ~field:"ETAG" (Assets.etag kind) in + (* TODO content-type *) + let* () = Vif.Response.add ~field:"content-type" "html; charset=utf-8" in Vif.Response.respond `OK let terms = static Assets.Terms diff --git a/src/util.ml b/src/util.ml index bc0b6afa..cd5894cb 100644 --- a/src/util.ml +++ b/src/util.ml @@ -13,7 +13,7 @@ let is_valid_filename, media_to_extension = ; (("image", "gif"), "gif") ] in - (* <> than the actual set of "supported" extension (depends on config files) *) + (* <> than the actual set of "supported" extension (which depends on config files) *) let all_known_extensions = mimetype_ext_assoc |> List.split |> snd in let is_valid_filename path = Fpath.mem_ext all_known_extensions path in let media_to_extension = function