diff --git a/vlib/vweb/dynamic_template_manager_test.v b/vlib/vweb/dynamic_template_manager_test.v
deleted file mode 100644
index 0bea60e5aa9aa1..00000000000000
--- a/vlib/vweb/dynamic_template_manager_test.v
+++ /dev/null
@@ -1,403 +0,0 @@
-module vweb
-
-import os
-import time
-
-const temp_dtm_dir = 'dynamic_template_manager_test'
-const temp_cache_dir = 'vcache'
-const temp_templates_dir = 'templates'
-const temp_html_fp = 'temp.html'
-const temp_html_n = 'temp'
-const vtmp_dir = os.vtmp_dir()
-
-fn testsuite_begin() {
- temp_folder := os.join_path(vweb.vtmp_dir, vweb.temp_dtm_dir)
- os.mkdir_all(temp_folder) or { panic(err) }
-
- vcache_path := os.join_path(temp_folder, vweb.temp_cache_dir)
- templates_path := os.join_path(temp_folder, vweb.temp_templates_dir)
-
- os.mkdir_all(vcache_path) or { panic(err) }
- os.mkdir_all(templates_path) or { panic(err) }
-
- temp_html_file := os.join_path(templates_path, vweb.temp_html_fp)
-
- html_content := '
-
-
-
- TEST
-
-
-
-
TEST
-
-
- '
-
- os.write_file(temp_html_file, html_content) or { panic(err) }
-}
-
-fn test_initialize_dtm() {
- dtm := init_dtm(false, 0)
- assert dtm.dtm_init_is_ok == true
-}
-
-fn test_test_and_clear_cache_files() {
- dtm := init_dtm(false, 0)
- dtm.test_and_clear_cache_files() or { panic(err) }
-
- count_cache_files := os.ls(dtm.template_cache_folder) or { panic(err) }
- assert count_cache_files.len == 0
-}
-
-fn test_create_template_cache_and_display_html() {
- mut dtm := init_dtm(true, max_size_data_in_memory)
- defer {
- dtm.stop_cache_handler()
- }
- html := dtm.create_cache()
- assert html.len > 10
-}
-
-fn test_get_cache() {
- mut dtm := init_dtm(true, max_size_data_in_memory)
- dtm.create_cache()
- defer {
- dtm.stop_cache_handler()
- }
- dtm_placeholers := map[string]DtmMultiTypeMap{}
- temp_html_file := os.join_path(dtm.template_folder, vweb.temp_html_fp)
- html_mem := dtm.get_cache(vweb.temp_html_n, temp_html_file, &dtm_placeholers)
- assert html_mem.len > 10
-}
-
-fn test_return_cache_info_isexistent() {
- mut dtm := init_dtm(false, 0)
- path_template := os.join_path(dtm.template_folder, vweb.temp_html_fp)
- lock dtm.template_caches {
- dtm.template_caches << TemplateCache{
- id: 1
- path: path_template
- }
- }
- lock dtm.nbr_of_remaining_template_request {
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 1
- }
- }
- cache_exists, _, _, _, _, _, _, _ := dtm.return_cache_info_isexistent(path_template)
- assert cache_exists == true
- lock dtm.template_caches {
- dtm.template_caches[0].id_redirection = 2
- dtm.template_caches << TemplateCache{
- id: 2
- path: path_template
- id_redirection: 3
- }
- dtm.template_caches << TemplateCache{
- id: 3
- path: path_template
- id_redirection: 4
- }
- dtm.template_caches << TemplateCache{
- id: 4
- path: path_template
- id_redirection: 5
- }
- dtm.template_caches << TemplateCache{
- id: 5
- path: path_template
- }
- }
- lock dtm.nbr_of_remaining_template_request {
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 2
- }
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 3
- }
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 4
- }
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 5
- }
- }
- _, id, _, _, _, _, _, _ := dtm.return_cache_info_isexistent(path_template)
- assert id == 5
-}
-
-fn test_remaining_template_request() {
- mut dtm := init_dtm(false, 0)
-
- lock dtm.nbr_of_remaining_template_request {
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 1
- }
-
- dtm.remaining_template_request(true, 1)
- assert dtm.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 1
- dtm.remaining_template_request(true, 1)
- assert dtm.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 2
- dtm.remaining_template_request(false, 1)
- assert dtm.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 1
- dtm.remaining_template_request(false, 1)
- assert dtm.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 0
- }
-}
-
-fn test_check_html_and_placeholders_size() {
- dtm := init_dtm(false, 0)
- temp_html_file := os.join_path(dtm.template_folder, vweb.temp_html_fp)
- placeholders := map[string]DtmMultiTypeMap{}
-
- path, filename := dtm.check_html_and_placeholders_size(temp_html_file, &placeholders) or {
- panic(err)
- }
-
- assert path.len > 10
- assert filename.len > 3
-}
-
-fn test_chandler_prevent_cache_duplicate_request() {
- dtm := init_dtm(false, 0)
- temp_html_file := os.join_path(dtm.template_folder, vweb.temp_html_fp)
-
- lock dtm.template_caches {
- dtm.template_caches << TemplateCache{
- id: 1
- path: temp_html_file
- cache_request: .new
- }
- dtm.template_caches << TemplateCache{
- id: 2
- path: temp_html_file
- cache_request: .update
- last_template_mod: i64(1)
- }
- dtm.template_caches << TemplateCache{
- id: 3
- path: temp_html_file
- cache_request: .exp_update
- last_template_mod: i64(1)
- generate_at: i64(100)
- }
- dtm.template_caches << TemplateCache{
- id: 4
- cache_request: .delete
- }
- }
- new_cache := TemplateCache{
- id: 5
- path: temp_html_file
- cache_request: .new
- }
- update_cache := TemplateCache{
- id: 6
- path: temp_html_file
- cache_request: .update
- last_template_mod: i64(1)
- }
- exp_update_cache := TemplateCache{
- id: 7
- path: temp_html_file
- cache_request: .exp_update
- last_template_mod: i64(1)
- generate_at: i64(10)
- cache_delay_expiration: i64(10)
- }
- delete_cache := TemplateCache{
- id: 4
- cache_request: .delete
- }
- mut is_duplicate := dtm.chandler_prevent_cache_duplicate_request(&new_cache)
- assert is_duplicate == true
- is_duplicate = dtm.chandler_prevent_cache_duplicate_request(&update_cache)
- assert is_duplicate == true
- is_duplicate = dtm.chandler_prevent_cache_duplicate_request(&exp_update_cache)
- assert is_duplicate == true
- is_duplicate = dtm.chandler_prevent_cache_duplicate_request(&delete_cache)
- assert is_duplicate == false
-
- lock dtm.template_caches {
- dtm.template_caches.delete(3)
- }
-
- is_duplicate = dtm.chandler_prevent_cache_duplicate_request(&delete_cache)
- assert is_duplicate == true
-}
-
-fn test_chandler_clear_specific_cache() {
- mut dtm := init_dtm(true, 0)
- defer {
- dtm.stop_cache_handler()
- }
- dtm.create_cache()
- lock dtm.template_caches {
- cache_file := os.join_path(dtm.template_cache_folder, '${dtm.template_caches[0].name}_${dtm.template_caches[0].checksum}.cache')
- index, is_success := dtm.chandler_clear_specific_cache(dtm.template_caches[0].id)
- assert is_success == true
- assert index == 0
- cache_exist := os.exists(cache_file)
- assert cache_exist == false
- }
-}
-
-fn test_chandler_remaining_cache_template_used() {
- mut dtm := init_dtm(false, 0)
- lock dtm.nbr_of_remaining_template_request {
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 1
- nbr_of_remaining_request: 0
- }
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 2
- nbr_of_remaining_request: 1
- need_to_delete: true
- }
- dtm.nbr_of_remaining_template_request << RemainingTemplateRequest{
- id: 3
- nbr_of_remaining_request: 0
- need_to_delete: true
- }
- }
- mut can_delete := dtm.chandler_remaining_cache_template_used(CacheRequest.update,
- 3, 3)
- assert can_delete == true
- can_delete = dtm.chandler_remaining_cache_template_used(CacheRequest.update, 2, 2)
- assert can_delete == false
- can_delete = dtm.chandler_remaining_cache_template_used(CacheRequest.delete, 1, 0)
- assert can_delete == true
- can_delete = dtm.chandler_remaining_cache_template_used(CacheRequest.new, 4, 0)
- assert can_delete == true
-}
-
-fn test_parse_html_file() {
- mut dtm := init_dtm(false, 0)
- temp_folder := os.join_path(vweb.vtmp_dir, vweb.temp_dtm_dir)
- templates_path := os.join_path(temp_folder, vweb.temp_templates_dir)
- temp_html_file := os.join_path(templates_path, vweb.temp_html_fp)
-
- mut placeholders := map[string]DtmMultiTypeMap{}
-
- is_compressed := true
- html, content_checksum := dtm.parse_html_file(temp_html_file, vweb.temp_html_n, &placeholders,
- is_compressed)
-
- assert html.len > 0
- if placeholders.len > 0 {
- assert content_checksum.len > 0
- } else {
- assert content_checksum.len == 0
- }
-}
-
-fn test_test_if_cache_delay_iscorrect() {
- test_if_cache_delay_iscorrect(i64(300), vweb.temp_html_n) or { assert false }
-
- test_if_cache_delay_iscorrect(i64(-100), vweb.temp_html_n) or { assert true }
-}
-
-fn test_cache_request_route() {
- mut is_cache_exist := true
- mut cache_delay_expiration := i64(400)
- mut last_template_mod := get_current_unix_timestamp()
- mut test_current_template_mod := last_template_mod
- mut cache_del_exp := 300
- mut gen_at := last_template_mod
- mut content_checksum := 'checksumtest1'
- mut current_content_checksum := 'checksumtest2'
-
- mut request_type := cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
- test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
- content_checksum, current_content_checksum)
-
- assert request_type == CacheRequest.update
-
- current_content_checksum = 'checksumtest1'
-
- request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
- test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
- content_checksum, current_content_checksum)
-
- assert request_type == CacheRequest.cached
-
- gen_at = (last_template_mod - 500)
-
- request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
- test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
- content_checksum, current_content_checksum)
-
- assert request_type == CacheRequest.exp_update
-
- is_cache_exist = false
-
- request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
- test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
- content_checksum, current_content_checksum)
-
- assert request_type == CacheRequest.new
-}
-
-fn test_cache_handler() {
- mut dtm := init_dtm(true, max_size_data_in_memory)
- defer {
- dtm.stop_cache_handler()
- }
- dtm.create_cache()
- path_f := os.join_path(dtm.template_folder, vweb.temp_html_fp)
- lock dtm.template_caches {
- assert dtm.template_caches[0].id == 1
- assert dtm.template_caches[0].name == vweb.temp_html_n
- assert dtm.template_caches[0].path == path_f
- }
- dtm.id_to_handlered = 1
- dtm.ch_cache_handler <- TemplateCache{
- id: 1
- cache_request: .delete
- }
- time.sleep(1 * time.millisecond)
- lock dtm.template_caches {
- assert dtm.template_caches.len == 0
- }
-}
-
-fn testsuite_end() {
- temp_folder := os.join_path(vweb.vtmp_dir, vweb.temp_dtm_dir)
- os.rmdir_all(temp_folder) or {}
-}
-
-// Utilities function :
-
-fn init_dtm(b bool, m int) &DynamicTemplateManager {
- temp_folder := os.join_path(vweb.vtmp_dir, vweb.temp_dtm_dir)
- vcache_path := os.join_path(temp_folder, vweb.temp_cache_dir)
- templates_path := os.join_path(temp_folder, vweb.temp_templates_dir)
-
- mut ctx := Context{}
- mut dtm := create_dtm()
-
- init_params := DynamicTemplateManagerInitialisationParams{
- active_cache_server: b
- max_size_data_in_mem: m
- test_cache_dir: vcache_path
- test_template_dir: templates_path
- }
-
- ctx.initialize_dtm(mut dtm, init_params) or { panic(err) }
-
- return dtm
-}
-
-fn (mut dtm DynamicTemplateManager) create_cache() string {
- temp_html_file := os.join_path(dtm.template_folder, vweb.temp_html_fp)
- html_last_mod := os.file_last_mod_unix(temp_html_file)
- c_time := get_current_unix_timestamp()
- cache_delay_exp := i64(500)
- placeholder := map[string]DtmMultiTypeMap{}
- html := dtm.create_template_cache_and_display_html(.new, html_last_mod, c_time, temp_html_file,
- vweb.temp_html_n, cache_delay_exp, &placeholder)
- time.sleep(1 * time.millisecond)
- return html
-}
diff --git a/vlib/vweb/tests/dynamic_template_manager_test_server/dynamic_template_manager_test_server.v b/vlib/vweb/tests/dynamic_template_manager_test_server/dynamic_template_manager_test_server.v
index fc1b01a3092676..ee2fcf882dc88c 100644
--- a/vlib/vweb/tests/dynamic_template_manager_test_server/dynamic_template_manager_test_server.v
+++ b/vlib/vweb/tests/dynamic_template_manager_test_server/dynamic_template_manager_test_server.v
@@ -1,13 +1,14 @@
import vweb
import time
+import x.templating.dtm
struct App {
vweb.Context
pub mut:
- dtm &vweb.DynamicTemplateManager = vweb.create_dtm()
- shared_data_string []string = []string{} @[vweb_global]
- shared_data_int []int = []int{} @[vweb_global]
- shared_switch int = 1 @[vweb_global]
+ dtm &dtm.DynamicTemplateManager = dtm.create_dtm() @[vweb_global]
+ shared_data_string []string = []string{} @[vweb_global]
+ shared_data_int []int = []int{} @[vweb_global]
+ shared_switch int = 1 @[vweb_global]
}
fn main() {
@@ -21,7 +22,7 @@ fn main() {
app.shared_data_int << 123456
app.shared_data_int << 7891011
- app.initialize_dtm(mut app.dtm) or { eprintln(err) }
+ dtm.initialize_dtm(mut app.dtm) or { eprintln(err) }
/*
app.initialize_dtm(mut &app.dtm,
compress_html: false
@@ -35,17 +36,18 @@ fn main() {
@['/']
pub fn (mut app App) index() vweb.Result {
- mut tmpl_var := map[string]vweb.DtmMultiTypeMap{}
+ mut tmpl_var := map[string]dtm.DtmMultiTypeMap{}
tmpl_var['title'] = app.shared_data_string[app.shared_switch]
tmpl_var['non_string_type'] = app.shared_data_int[app.shared_switch]
tmpl_var['string_type'] = app.shared_data_string[4]
tmpl_var['html_#includehtml'] = app.shared_data_string[app.shared_switch + 2]
// You can also modify the HTML template file directly without having to recompile the application.
- return app.serve_dynamic_template('index.html',
+ html_content := app.dtm.serve_dynamic_template('index.html',
placeholders: &tmpl_var
- cache_delay_expiration: vweb.cache_delay_expiration_at_min
+ cache_delay_expiration: dtm.cache_delay_expiration_at_min
)
+ return app.html(html_content)
}
fn (mut app App) update_data() {
diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v
index 08930a46a1361d..fd7b4ff56473c4 100644
--- a/vlib/vweb/vweb.v
+++ b/vlib/vweb/vweb.v
@@ -158,8 +158,6 @@ pub:
req http.Request
// TODO Response
pub mut:
- // DTM reference field
- dtm &DynamicTemplateManager = unsafe { nil }
done bool
// time.ticks() from start of vweb connection handle.
// You can use it to determine how much time is spent on your request.
@@ -647,10 +645,7 @@ fn new_request_app[T](global_app &T, ctx Context, tid int) &T {
request_app.Context.static_files = global_app.static_files.clone()
request_app.Context.static_mime_types = global_app.static_mime_types.clone()
request_app.Context.static_hosts = global_app.static_hosts.clone()
- // TODO: Temporarily using this, to assign DTM due to V's current limitations with shared field handling at comptime. Needs future revision.
- unsafe {
- request_app.Context.dtm = &voidptr(global_app.dtm)
- }
+
return request_app
}
diff --git a/vlib/vweb/dynamic_template_manager.v b/vlib/x/templating/dtm/dynamic_template_manager.v
similarity index 84%
rename from vlib/vweb/dynamic_template_manager.v
rename to vlib/x/templating/dtm/dynamic_template_manager.v
index 2990be8c35dba5..d8c171038e4073 100644
--- a/vlib/vweb/dynamic_template_manager.v
+++ b/vlib/x/templating/dtm/dynamic_template_manager.v
@@ -1,10 +1,11 @@
-module vweb
+module dtm
import os
import v.parser
import crypto.sha256
import time
import regex
+import x.templating
// These are all the types of dynamic values that the DTM allows to be returned in the context of a map
type DtmMultiTypeMap = f32 | f64 | i16 | i64 | i8 | int | string | u16 | u32 | u64 | u8
@@ -26,9 +27,11 @@ const max_placeholders_key_size = 50
// Sets the maximum character length for placeholder values.
const max_placeholders_value_size = 3000
-const message_signature = '[Vweb DTM]'
-const message_signature_info = '[Vweb DTM] Info :'
-const message_signature_error = '[Vweb DTM] Error :'
+const internat_server_error = 'Internal Server Error'
+
+const message_signature = '[Dynamic Template Manager]'
+const message_signature_info = '[Dynamic Template Manager] Info :'
+const message_signature_error = '[Dynamic Template Manager] Error :'
pub enum CacheStorageMode {
memory
@@ -57,7 +60,7 @@ mut:
template_caches shared []TemplateCache = []TemplateCache{}
// counter for each individual TemplateCache created/updated
id_counter int = 1
- ch_cache_handler chan TemplateCache = chan TemplateCache{cap: vweb.cache_handler_channel_cap}
+ ch_cache_handler chan TemplateCache = chan TemplateCache{cap: dtm.cache_handler_channel_cap}
// 'id_to_handlered' field is used exclusively by the cache handler to update or delete specific 'TemplateCache' in the cache database.
id_to_handlered int
close_cache_handler bool
@@ -65,7 +68,7 @@ mut:
compress_html bool = true
active_cache_server bool = true
// Initialisation of max data size in memory storage
- max_size_data_in_memory int = vweb.max_size_data_in_memory
+ max_size_data_in_memory int = dtm.max_size_data_in_memory
// This array is designed to store a control process that checks whether cached data is currently in use while simultaneously handling expiration.
// This allows for the harmonious management of both aspects and facilitates the necessary actions.
nbr_of_remaining_template_request shared []RemainingTemplateRequest = []RemainingTemplateRequest{}
@@ -126,7 +129,7 @@ mut:
@[params]
pub struct TemplateCacheParams {
placeholders &map[string]DtmMultiTypeMap = &map[string]DtmMultiTypeMap{}
- cache_delay_expiration i64 = vweb.cache_delay_expiration_by_default
+ cache_delay_expiration i64 = dtm.cache_delay_expiration_by_default
}
// These parameters are used with 'initialize_dtm' function. (See below at initialize_dtm comment)
@@ -134,7 +137,7 @@ pub struct TemplateCacheParams {
pub struct DynamicTemplateManagerInitialisationParams {
compress_html bool = true
active_cache_server bool = true
- max_size_data_in_mem int = vweb.max_size_data_in_memory
+ max_size_data_in_mem int = dtm.max_size_data_in_memory
test_cache_dir string
test_template_dir string
}
@@ -147,9 +150,9 @@ pub fn create_dtm() &DynamicTemplateManager {
return &DynamicTemplateManager{}
}
-// pub fn (mut Context) initialize_dtm(&DynamicTemplateManager, string, DynamicTemplateManagerInitialisationParams) return !
+// pub fn initialize_dtm(&DynamicTemplateManager, string, DynamicTemplateManagerInitialisationParams) return !
//
-// Initializes the 'DynamicTemplateManager' with the storage mode, cache folder path and set a persistent reference of DTM in the Vweb global Context
+// Initializes the 'DynamicTemplateManager' with the storage mode, cache folder path and set a persistent reference of DTM in the dtm global Context
// The Dynamic Template Manager (DTM) requires this initialization function to be operational.
// A "vcache" directory must be created at the root of the project (where the executable is located) to use the DTM.
// Initalisation params are :
@@ -160,7 +163,7 @@ pub fn create_dtm() &DynamicTemplateManager {
// - test_template_dir: 'type string' Used only for DTM test file, parameter is ignored otherwise.
//
// vfmt off
-pub fn (mut ctx Context) initialize_dtm(mut dtm &DynamicTemplateManager, dtm_init_params DynamicTemplateManagerInitialisationParams) ! {
+pub fn initialize_dtm(mut dtmref &DynamicTemplateManager, dtm_init_params DynamicTemplateManagerInitialisationParams) ! {
// vfmt on
mut dir_path := ''
mut dir_html_path := ''
@@ -173,48 +176,44 @@ pub fn (mut ctx Context) initialize_dtm(mut dtm &DynamicTemplateManager, dtm_ini
}
// Control if 'vcache' folder exist in the root project
if os.exists(dir_path) && os.is_dir(dir_path) {
- dtm.template_cache_folder = dir_path
+ dtmref.template_cache_folder = dir_path
// WARNING: When setting the directory for caching files and for testing purposes,
// 'test_and_clear_cache_files' function will delete all "*.cache" or "*.tmp" files inside the specified 'vcache' directory in the project root's. Ensure that
// directory used for the cache does not contain any important files.
- dtm.test_and_clear_cache_files()!
+ dtmref.test_and_clear_cache_files()!
// Control if 'templates' folder exist in the root project
if !os.exists(dir_html_path) && !os.is_dir(dir_html_path) {
- return error('${vweb.message_signature_error} The templates directory at the project root does not exist. Please create a "templates" directory at the root of your project with appropriate read permissions. This is a mandatory step for using the Dynamic Template Manager (DTM). Current path attempted for create the templates folder: "${dir_html_path}"')
+ return error('${dtm.message_signature_error} The templates directory at the project root does not exist. Please create a "templates" directory at the root of your project with appropriate read permissions. This is a mandatory step for using the Dynamic Template Manager (DTM). Current path attempted for create the templates folder: "${dir_html_path}"')
} else {
- dtm.template_folder = dir_html_path
+ dtmref.template_folder = dir_html_path
}
} else {
- return error('${vweb.message_signature_error} The cache storage directory at the project root does not exist. Please create a "vcache" directory at the root of your project with appropriate read/write permissions. This is a mandatory step for using the Dynamic Template Manager (DTM). Current path attempted for create the cache folder: "${dir_path}"')
+ return error('${dtm.message_signature_error} The cache storage directory at the project root does not exist. Please create a "vcache" directory at the root of your project with appropriate read/write permissions. This is a mandatory step for using the Dynamic Template Manager (DTM). Current path attempted for create the cache folder: "${dir_path}"')
}
// Validates the 'max_size_data_in_mem' setting in 'dtm_init_params'. If it's within the valid range, it's applied; otherwise, default value is used.
- if dtm_init_params.max_size_data_in_mem <= vweb.max_size_data_in_memory
+ if dtm_init_params.max_size_data_in_mem <= dtm.max_size_data_in_memory
&& dtm_init_params.max_size_data_in_mem >= 0 {
- dtm.max_size_data_in_memory = dtm_init_params.max_size_data_in_mem
+ dtmref.max_size_data_in_memory = dtm_init_params.max_size_data_in_mem
} else {
mut type_error := 'exceeds'
if dtm_init_params.max_size_data_in_mem < 0 {
type_error = 'is invalid for define'
}
- eprintln('${vweb.message_signature_info} The value "${dtm_init_params.max_size_data_in_mem}KB" ${type_error} the memory storage limit. It will not be considered, and the limit will be set to ${vweb.max_size_data_in_memory}KB.')
+ eprintln('${dtm.message_signature_info} The value "${dtm_init_params.max_size_data_in_mem}KB" ${type_error} the memory storage limit. It will not be considered, and the limit will be set to ${dtm.max_size_data_in_memory}KB.')
}
// Disable light HTML compression if user doesn't required. ( By default is ON )
if !dtm_init_params.compress_html {
- dtm.compress_html = false
+ dtmref.compress_html = false
}
// Disable cache handler if user doesn't required. Else, new thread is used to start the cache system. ( By default is ON )
if !dtm_init_params.active_cache_server {
- dtm.active_cache_server = false
+ dtmref.active_cache_server = false
} else {
- spawn dtm.cache_handler()
- }
- // Include a persistent reference of DTM in the Vweb global Context
- unsafe {
- ctx.dtm = &dtm
+ spawn dtmref.cache_handler()
}
- dtm.dtm_init_is_ok = true
- println('${vweb.message_signature} Dynamic Template Manager mode activated')
+ dtmref.dtm_init_is_ok = true
+ println('${dtm.message_signature} Dynamic Template Manager mode activated')
}
/*
@@ -231,7 +230,7 @@ fn init_cache_block_middleware(cache_dir string, mut dtm &DynamicTemplateManager
}
*/
-// pub fn (mut Context) serve_dynamic_template(string, TemplateCacheParams) return vweb.Result
+// pub fn (mut tm DynamicTemplateManager) serve_dynamic_template(string, TemplateCacheParams) return string
//
// Serves dynamic template based on its full path and parameters. Manages the cache and returns generated HTML.
// It the unique public function of DTM ( with initialization ), but requires an initialization via 'initialize_dtm' to running.
@@ -239,13 +238,13 @@ fn init_cache_block_middleware(cache_dir string, mut dtm &DynamicTemplateManager
// However, it allows the use of subfolder paths within the 'templates' directory,
// enabling users to structure their templates in a way that best suits their project's organization.
//
-pub fn (mut ctx Context) serve_dynamic_template(tmpl_path string, tmpl_var TemplateCacheParams) Result {
- if ctx.dtm.dtm_init_is_ok {
- file_path, tmpl_name := ctx.dtm.check_html_and_placeholders_size(tmpl_path, tmpl_var.placeholders) or {
- return ctx.html(err.msg())
+pub fn (mut tm DynamicTemplateManager) serve_dynamic_template(tmpl_path string, tmpl_var TemplateCacheParams) string {
+ if tm.dtm_init_is_ok {
+ file_path, tmpl_name := tm.check_html_and_placeholders_size(tmpl_path, tmpl_var.placeholders) or {
+ return err.msg()
}
// If cache exist, return necessary fields else, 'is_cache_exist' return false.
- is_cache_exist, id, path, mut last_template_mod, gen_at, cache_del_exp, c_time, content_checksum := ctx.dtm.return_cache_info_isexistent(file_path)
+ is_cache_exist, id, path, mut last_template_mod, gen_at, cache_del_exp, c_time, content_checksum := tm.return_cache_info_isexistent(file_path)
mut html := ''
// Definition of several variables used to assess the need for cache updates.sss
// This determination is based on modifications within the HTML template itself.
@@ -286,28 +285,28 @@ pub fn (mut ctx Context) serve_dynamic_template(tmpl_path string, tmpl_var Templ
match cash_req {
.new {
// Create a new cache
- html = ctx.dtm.create_template_cache_and_display_html(cash_req, last_template_mod,
+ html = tm.create_template_cache_and_display_html(cash_req, last_template_mod,
c_time, file_path, tmpl_name, tmpl_var.cache_delay_expiration, tmpl_var.placeholders)
// println('create cache : ${cash_req}')
}
.update, .exp_update {
// Update an existing cache
- ctx.dtm.id_to_handlered = id
- html = ctx.dtm.create_template_cache_and_display_html(cash_req, test_current_template_mod,
+ tm.id_to_handlered = id
+ html = tm.create_template_cache_and_display_html(cash_req, test_current_template_mod,
c_time, file_path, tmpl_name, tmpl_var.cache_delay_expiration, tmpl_var.placeholders)
// println('update cache : ${cash_req}')
}
else {
// Use the provided cache of html template.
- html = ctx.dtm.get_cache(tmpl_name, path, tmpl_var.placeholders)
+ html = tm.get_cache(tmpl_name, path, tmpl_var.placeholders)
// println('get cache : ${cash_req}')
}
}
- return ctx.html(html)
+ return html
} else {
- ctx.dtm.stop_cache_handler()
- eprintln('${vweb.message_signature_error} The initialization phase of DTM has failed. Therefore, you cannot use it. Please address the errors and then restart the Vweb server.')
- return ctx.html(http_500.body)
+ tm.stop_cache_handler()
+ eprintln('${dtm.message_signature_error} The initialization phase of DTM has failed. Therefore, you cannot use it. Please address the errors and then restart the dtm server.')
+ return dtm.internat_server_error
}
}
@@ -325,25 +324,25 @@ pub fn (mut ctx Context) serve_dynamic_template(tmpl_path string, tmpl_var Templ
// directory used for the cache does not contain any important files.
//
fn (tm DynamicTemplateManager) test_and_clear_cache_files() ! {
- // println('${vweb.message_signature} WARNING! DTM needs to perform some file tests in the 'vcache' directory in your project. This operation will erase all "*.cache" or "*.tmp" files content in the folder : "${tm.template_cache_folder}"')
+ // println('${message_signature} WARNING! DTM needs to perform some file tests in the 'vcache' directory in your project. This operation will erase all "*.cache" or "*.tmp" files content in the folder : "${tm.template_cache_folder}"')
// println('Do you want to continue the operation? (yes/no)')
// mut user_response := os.input('>').to_lower()
// if user_response != 'yes' && user_response != 'y' {
- // return error('${vweb.message_signature_error} Operation cancelled by the user. DTM initialization failed.')
+ // return error('${message_signature_error} Operation cancelled by the user. DTM initialization failed.')
// } else {
file_p := os.join_path(tm.template_cache_folder, 'test.tmp')
// Create a text file for test permission access
mut f := os.create(file_p) or {
- return error('${vweb.message_signature_error} Files are not writable. Test fail, DTM initialization failed : ${err.msg()}')
+ return error('${dtm.message_signature_error} Files are not writable. Test fail, DTM initialization failed : ${err.msg()}')
}
f.close()
// Read the previous text file for test permission access
os.read_file(file_p) or {
- return error('${vweb.message_signature_error} Files are not readable. Test fail, DTM initialization failed : ${err.msg()}')
+ return error('${dtm.message_signature_error} Files are not readable. Test fail, DTM initialization failed : ${err.msg()}')
}
// List all files in the cache folder
files_list := os.ls(tm.template_cache_folder) or {
- return error('${vweb.message_signature_error} While listing the cache directorie files, DTM initialization failed : ${err.msg()}')
+ return error('${dtm.message_signature_error} While listing the cache directorie files, DTM initialization failed : ${err.msg()}')
}
// Delete one by one "*.cache" or "*.tmp" files in the previous file list
for file in files_list {
@@ -351,7 +350,7 @@ fn (tm DynamicTemplateManager) test_and_clear_cache_files() ! {
file_extension := os.file_ext(file_path).to_lower()
if file_extension in ['.tmp', '.cache'] {
os.rm(file_path) or {
- eprintln('${vweb.message_signature_error} While deleting the cache file: ${file_path}. DTM initialization failed : ${err.msg()}')
+ eprintln('${dtm.message_signature_error} While deleting the cache file: ${file_path}. DTM initialization failed : ${err.msg()}')
return
}
}
@@ -380,27 +379,26 @@ fn (tm DynamicTemplateManager) check_html_and_placeholders_size(f_path string, t
file_name := file_name_with_ext.all_before_last('.')
// Performs a basic check of the file extension.
ext := os.file_ext(html_file)
- content_type := mime_types[ext]
- if content_type != 'text/html' {
- eprintln('${vweb.message_signature_error} ${html_file}, is not a HTML file')
- return error(http_500.body)
+ if ext != '.html' {
+ eprintln('${dtm.message_signature_error} ${html_file}, is not a HTML file')
+ return error(dtm.internat_server_error)
}
// Control placeholder key and value sizes
for key, value in tmpl_var {
- if key.str().len > vweb.max_placeholders_key_size {
- eprintln('${vweb.message_signature_error} Length of placeholder key "${key}" exceeds the maximum allowed size for HTML content in file: ${html_file}. Max allowed size: ${vweb.max_placeholders_key_size} characters.')
- return error(http_500.body)
+ if key.str().len > dtm.max_placeholders_key_size {
+ eprintln('${dtm.message_signature_error} Length of placeholder key "${key}" exceeds the maximum allowed size for HTML content in file: ${html_file}. Max allowed size: ${dtm.max_placeholders_key_size} characters.')
+ return error(dtm.internat_server_error)
}
- if value.str().len > vweb.max_placeholders_value_size {
- eprintln('${vweb.message_signature_error} Length of placeholder value for key "${key}" exceeds the maximum allowed size for HTML content in file: ${html_file}. Max allowed size: ${vweb.max_placeholders_value_size} characters.')
- return error(http_500.body)
+ if value.str().len > dtm.max_placeholders_value_size {
+ eprintln('${dtm.message_signature_error} Length of placeholder value for key "${key}" exceeds the maximum allowed size for HTML content in file: ${html_file}. Max allowed size: ${dtm.max_placeholders_value_size} characters.')
+ return error(dtm.internat_server_error)
}
}
// If all is ok, return full path of HTML template file and HTML filename without extension
return html_file, file_name
} else {
- eprintln("${vweb.message_signature_error} Template : '${html_file}' not found. Ensure all HTML templates are located in the 'templates' directory at the project's root.")
- return error(http_500.body)
+ eprintln("${dtm.message_signature_error} Template : '${html_file}' not found. Ensure all HTML templates are located in the 'templates' directory at the project's root.")
+ return error(dtm.internat_server_error)
}
}
@@ -418,16 +416,16 @@ fn (tm DynamicTemplateManager) check_html_and_placeholders_size(f_path string, t
//
fn (mut tm DynamicTemplateManager) create_template_cache_and_display_html(tcs CacheRequest, last_template_mod i64, c_time i64, file_path string, tmpl_name string, cache_delay_expiration i64, placeholders &map[string]DtmMultiTypeMap) string {
// Control if cache delay expiration is correctly setted. See the function itself for more details.
- test_if_cache_delay_iscorrect(cache_delay_expiration, tmpl_name) or {
+ check_if_cache_delay_iscorrect(cache_delay_expiration, tmpl_name) or {
eprintln(err)
- return http_500.body
+ return dtm.internat_server_error
}
// Parses the HTML and stores the rendered output in the variable. See the function itself for more details.
mut html, content_checksum := tm.parse_html_file(file_path, tmpl_name, placeholders,
tm.compress_html)
// If caching is enabled and the HTML content is valid, this section creates a temporary cache file, which is then used by the cache manager.
// If successfully temporary is created, a cache creation/update notification is sent through its dedicated channel to the cache manager
- if cache_delay_expiration != -1 && html != http_500.body && tm.active_cache_server {
+ if cache_delay_expiration != -1 && html != dtm.internat_server_error && tm.active_cache_server {
op_success, tmp_name := tm.create_temp_cache(html, file_path, c_time)
if op_success {
tm.ch_cache_handler <- TemplateCache{
@@ -482,11 +480,11 @@ fn (tm DynamicTemplateManager) create_temp_cache(html &string, f_path string, ts
// Converts the HTML content into a byte array
html_bytes := html.bytes()
mut f := os.create(cache_path) or {
- eprintln('${vweb.message_signature_error} Cannot create tempory cache file : ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cannot create tempory cache file : ${err.msg()}')
return false, ''
}
f.write(html_bytes) or {
- eprintln('${vweb.message_signature_error} Cannot write in temporary cache file : ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cannot write in temporary cache file : ${err.msg()}')
f.close()
return false, ''
}
@@ -514,8 +512,8 @@ fn (mut tm DynamicTemplateManager) get_cache(name string, path string, placehold
// Retrieve the HTML render from the file cache in disk and convert it to a string.
file_name := os.join_path(tm.template_cache_folder, '${value.name}_${value.checksum}.cache')
r_b_html := os.read_bytes(file_name) or {
- eprintln('${vweb.message_signature_error} Get_cache() cannot read template cache file ${value.name} : ${err.msg()} ')
- return http_500.body
+ eprintln('${dtm.message_signature_error} Get_cache() cannot read template cache file ${value.name} : ${err.msg()} ')
+ return dtm.internat_server_error
}
html = r_b_html.bytestr()
}
@@ -641,7 +639,7 @@ fn (mut tm DynamicTemplateManager) cache_handler() {
mut tc := <-tm.ch_cache_handler {
// Close handler if asked.
if tm.close_cache_handler {
- eprintln('${vweb.message_signature_info} Cache manager has been successfully stopped. Please consider restarting the application if needed.')
+ eprintln('${dtm.message_signature_info} Cache manager has been successfully stopped. Please consider restarting the application if needed.')
break
}
f_path_tmp := os.join_path(tm.template_cache_folder, tc.tmp_name_file)
@@ -661,7 +659,7 @@ fn (mut tm DynamicTemplateManager) cache_handler() {
tc.cache_storage_mode = .disk
}
file_data := os.read_bytes(f_path_tmp) or {
- eprintln('${vweb.message_signature_error} Cache Handler : Failed to read tmp file, cache server will be stopped, you need to fix and restart application: ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cache Handler : Failed to read tmp file, cache server will be stopped, you need to fix and restart application: ${err.msg()}')
break
}
@@ -673,7 +671,7 @@ fn (mut tm DynamicTemplateManager) cache_handler() {
// If the cache is stored in memory, the temporary file is destroyed.
tc.html_data = file_data
os.rm(f_path_tmp) or {
- eprintln('${vweb.message_signature_error} Cache Handler : While deleting the tmp cache file: "${f_path_tmp}", cache server will be stopped, you need to fix and restart application: ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cache Handler : While deleting the tmp cache file: "${f_path_tmp}", cache server will be stopped, you need to fix and restart application: ${err.msg()}')
break
}
}
@@ -682,7 +680,7 @@ fn (mut tm DynamicTemplateManager) cache_handler() {
new_cache_file_name := os.join_path(tm.template_cache_folder,
'${tc.name}_${tc.checksum}.cache')
os.mv(f_path_tmp, new_cache_file_name) or {
- eprintln('${vweb.message_signature_error} Cache Handler : Failed to rename tmp file, cache server will be stopped, you need to fix and restart application: ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cache Handler : Failed to rename tmp file, cache server will be stopped, you need to fix and restart application: ${err.msg()}')
break
}
}
@@ -720,7 +718,7 @@ fn (mut tm DynamicTemplateManager) cache_handler() {
}
} else if tc.cache_request != .delete {
os.rm(f_path_tmp) or {
- eprintln('${vweb.message_signature_error} Cache Handler : While deleting the tmp cache file: "${f_path_tmp}", cache server will be stopped, you need to fix and restart application: ${err.msg()}')
+ eprintln('${dtm.message_signature_error} Cache Handler : While deleting the tmp cache file: "${f_path_tmp}", cache server will be stopped, you need to fix and restart application: ${err.msg()}')
break
}
}
@@ -794,7 +792,7 @@ fn (mut tm DynamicTemplateManager) chandler_clear_specific_cache(id int) (int, b
.disk {
file_path := os.join_path(tm.template_cache_folder, '${value.name}_${value.checksum}.cache')
os.rm(file_path) or {
- eprintln('${vweb.message_signature_error} While deleting the specific cache file: ${file_path}, cache server will be stopped, you need to fix and restart application: : ${err.msg()}')
+ eprintln('${dtm.message_signature_error} While deleting the specific cache file: ${file_path}, cache server will be stopped, you need to fix and restart application: : ${err.msg()}')
break
}
}
@@ -888,7 +886,7 @@ fn (mut tm DynamicTemplateManager) stop_cache_handler() {
// Addressing this by adding a control mechanism is recommended for enhanced stability.
// For now, it is the user's responsibility to provide the correct HTML file(s) and HTML file(s)-content format.
//
-// TODO - Note that the function 'vlib/vweb/vweb.v : filter()' is currently used here.
+// TODO - Note that the function 'vlib/dtm/dtm.v : filter()' is currently used here.
// However, it is marked for relocation to the template render in the future.
// If this change is implemented, corresponding adjustments will also be needed in this function.
//
@@ -908,8 +906,8 @@ fn (mut tm DynamicTemplateManager) parse_html_file(file_path string, tmpl_name s
// To prevent runtime crashes related to template include directives error,
// this code snippet ensures that the paths in include directives '@include' are correct.
html_content := os.read_file(file_path) or {
- eprintln("${vweb.message_signature_error} Unable to read the file: '${file_path}' with HTML parser function.")
- return http_500.body, ''
+ eprintln("${dtm.message_signature_error} Unable to read the file: '${file_path}' with HTML parser function.")
+ return dtm.internat_server_error, ''
}
// TODO - The regex module in V does not support the use of escaped single quotes (') or double quotes (") in regex patterns, which can result in syntax errors.
// This limitation can cause runtime errors if double quotes are used in HTML templates with '@include' directives.
@@ -947,8 +945,8 @@ fn (mut tm DynamicTemplateManager) parse_html_file(file_path string, tmpl_name s
}
if directive_inclusion_error {
- eprintln("${vweb.message_signature_error} In the HTML template: '${file_path}', an error occurred in one of the '@include' directives. This could be due to the use of an invalid path: ${full_path}")
- return http_500.body, ''
+ eprintln("${dtm.message_signature_error} In the HTML template: '${file_path}', an error occurred in one of the '@include' directives. This could be due to the use of an invalid path: ${full_path}")
+ return dtm.internat_server_error, ''
}
}
mut p := parser.Parser{}
@@ -958,7 +956,7 @@ fn (mut tm DynamicTemplateManager) parse_html_file(file_path string, tmpl_name s
placeholders)
// This section completes the processing by replacing any placeholders that were not handled by the compiler template parser.
// If there are placeholders present, it iterates through them, applying necessary filters and substituting their values into the HTML content.
- // vweb.filter function used here. 'vlib/vweb.vweb.v line 1159.'
+ // dtm.filter function used here. 'vlib/dtm.dtm.v line 1159.'
mut combined_str := ''
mut current_content_checksum := ''
// Checks if there are any placeholders to process
@@ -971,25 +969,25 @@ fn (mut tm DynamicTemplateManager) parse_html_file(file_path string, tmpl_name s
// Converts value to string
temp_val := value.str()
// Filters the string value for safe HTML insertion
- val = filter(temp_val)
+ val = templating.filter(temp_val)
// Appends the original string value to the combined string for the content checksum
combined_str += temp_val
}
string {
// Checks if the placeholder allows HTML inclusion
- if key.ends_with(vweb.include_html_key_tag) {
+ if key.ends_with(dtm.include_html_key_tag) {
// Iterates over allowed HTML tags for inclusion
- for tag in vweb.allowed_tags {
+ for tag in dtm.allowed_tags {
// Escapes the HTML tag
- escaped_tag := filter(tag)
+ escaped_tag := templating.filter(tag)
// Replaces the escaped tags with actual HTML tags in the value
val = value.replace(escaped_tag, tag)
}
// Adjusts the placeholder key by removing the HTML inclusion tag
- key_m = key.all_before_last(vweb.include_html_key_tag)
+ key_m = key.all_before_last(dtm.include_html_key_tag)
} else {
// Filters the string value for safe HTML insertion
- val = filter(value)
+ val = templating.filter(value)
}
// Appends the string value to the combined string for the content checksum
combined_str += value
@@ -1035,7 +1033,7 @@ fn (mut tm DynamicTemplateManager) parse_html_file(file_path string, tmpl_name s
// TODO - This function does not currently handle the cleanup of all template directives typically managed by the Vlang compiler, such as conditional statements or loops....
// Implementation of these features will be necessary.
//
-// TODO - Note that the function 'vlib/vweb/vweb.v : filter()' is currently used here.
+// TODO - Note that the function 'vlib/dtm/dtm.v : filter()' is currently used here.
// However, it is marked for relocation to the template render in the future.
// If this change is implemented, corresponding adjustments will also be needed in this function.
//
@@ -1046,15 +1044,15 @@ fn (mut tm DynamicTemplateManager) clean_parsed_html(tmpl string, tmpl_name stri
end_marker := "')\n\n\t_tmpl_res_${tmpl_name} := sb_${tmpl_name}.str()"
// Searches for the start marker in the processed HTML content. Triggers an error if the start marker is not found.
start := tmpl.index(start_marker) or {
- eprintln("${vweb.message_signature_error} Start marker not found for '${tmpl_name}': ${err.msg()}")
- // vweb.filter function used here. 'vlib/vweb.vweb.v line 1159.'
- return filter(tmpl)
+ eprintln("${dtm.message_signature_error} Start marker not found for '${tmpl_name}': ${err.msg()}")
+ // dtm.filter function used here. 'vlib/dtm.dtm.v line 1159.'
+ return templating.filter(tmpl)
}
// Identifies the last occurrence of the end marker. Signals an error if it is missing.
end := tmpl.index_last(end_marker) or {
- eprintln("${vweb.message_signature_error} End marker not found for '${tmpl_name}': ${err.msg()}")
- // vweb.filter function used here. 'vlib/vweb.vweb.v line 1159.'
- return filter(tmpl)
+ eprintln("${dtm.message_signature_error} End marker not found for '${tmpl_name}': ${err.msg()}")
+ // dtm.filter function used here. 'vlib/dtm.dtm.v line 1159.'
+ return templating.filter(tmpl)
}
// Extracts the portion of HTML content between the start and end markers.
mut html := tmpl[start + start_marker.len..end]
@@ -1078,9 +1076,9 @@ fn (mut tm DynamicTemplateManager) clean_parsed_html(tmpl string, tmpl_name stri
placeholder_name := placeholder[1..]
// Checks if the placeholder or its variant with '_#includehtml' is not in the provided placeholders map.
if !(placeholder_name in provided_placeholders
- || (placeholder_name + vweb.include_html_key_tag) in provided_placeholders) {
+ || (placeholder_name + dtm.include_html_key_tag) in provided_placeholders) {
// If so, escapes the unresolved placeholder and replaces the original placeholder with the escaped version
- escaped_placeholder := filter(placeholder)
+ escaped_placeholder := templating.filter(placeholder)
html = html.replace(placeholder, escaped_placeholder)
}
}
@@ -1090,7 +1088,7 @@ fn (mut tm DynamicTemplateManager) clean_parsed_html(tmpl string, tmpl_name stri
return html
}
-// fn test_if_cache_delay_iscorrect(i64, string) return !
+// fn check_if_cache_delay_iscorrect(i64, string) return !
//
// Validates the user-specified cache expiration delay for HTML templates.
// It enforces three permissible delay settings:
@@ -1098,10 +1096,10 @@ fn (mut tm DynamicTemplateManager) clean_parsed_html(tmpl string, tmpl_name stri
// - A parameter of 0 for an infinite cache expiration delay
// - A parameter of -1 for no caching, meaning the HTML template is processed every time without being stored in the cache."
//
-fn test_if_cache_delay_iscorrect(cde i64, tmpl_name string) ! {
- if (cde != 0 && cde != -1 && cde < vweb.cache_delay_expiration_at_min)
- || (cde != 0 && cde != -1 && cde > vweb.cache_delay_expiration_at_max) {
- return error("${vweb.message_signature_error} The cache timeout for template '${tmpl_name}.html' cannot be set to a value less than '${vweb.cache_delay_expiration_at_min}' seconds and more than '${vweb.cache_delay_expiration_at_max}' seconds. Exception for the value '0' which means no cache expiration, and the value '-1' which means html generation without caching.")
+fn check_if_cache_delay_iscorrect(cde i64, tmpl_name string) ! {
+ if (cde != 0 && cde != -1 && cde < dtm.cache_delay_expiration_at_min)
+ || (cde != 0 && cde != -1 && cde > dtm.cache_delay_expiration_at_max) {
+ return error("${dtm.message_signature_error} The cache timeout for template '${tmpl_name}.html' cannot be set to a value less than '${dtm.cache_delay_expiration_at_min}' seconds and more than '${dtm.cache_delay_expiration_at_max}' seconds. Exception for the value '0' which means no cache expiration, and the value '-1' which means html generation without caching.")
}
}
diff --git a/vlib/x/templating/dtm/dynamic_template_manager_test.v b/vlib/x/templating/dtm/dynamic_template_manager_test.v
new file mode 100644
index 00000000000000..0661ec301735b8
--- /dev/null
+++ b/vlib/x/templating/dtm/dynamic_template_manager_test.v
@@ -0,0 +1,402 @@
+module dtm
+
+import os
+import time
+
+const temp_dtm_dir = 'dynamic_template_manager_test'
+const temp_cache_dir = 'vcache'
+const temp_templates_dir = 'templates'
+const temp_html_fp = 'temp.html'
+const temp_html_n = 'temp'
+const vtmp_dir = os.vtmp_dir()
+
+fn testsuite_begin() {
+ temp_folder := os.join_path(dtm.vtmp_dir, dtm.temp_dtm_dir)
+ os.mkdir_all(temp_folder) or { panic(err) }
+
+ vcache_path := os.join_path(temp_folder, dtm.temp_cache_dir)
+ templates_path := os.join_path(temp_folder, dtm.temp_templates_dir)
+
+ os.mkdir_all(vcache_path) or { panic(err) }
+ os.mkdir_all(templates_path) or { panic(err) }
+
+ temp_html_file := os.join_path(templates_path, dtm.temp_html_fp)
+
+ html_content := '
+
+
+
+ TEST
+
+
+
+
TEST
+
+
+ '
+
+ os.write_file(temp_html_file, html_content) or { panic(err) }
+}
+
+fn test_initialize_dtm() {
+ dtmi := init_dtm(false, 0)
+ assert dtmi.dtm_init_is_ok == true
+}
+
+fn test_test_and_clear_cache_files() {
+ dtmi := init_dtm(false, 0)
+ dtmi.test_and_clear_cache_files() or { panic(err) }
+
+ count_cache_files := os.ls(dtmi.template_cache_folder) or { panic(err) }
+ assert count_cache_files.len == 0
+}
+
+fn test_create_template_cache_and_display_html() {
+ mut dtmi := init_dtm(true, max_size_data_in_memory)
+ defer {
+ dtmi.stop_cache_handler()
+ }
+ html := dtmi.create_cache()
+ assert html.len > 10
+}
+
+fn test_get_cache() {
+ mut dtmi := init_dtm(true, max_size_data_in_memory)
+ dtmi.create_cache()
+ defer {
+ dtmi.stop_cache_handler()
+ }
+ dtm_placeholers := map[string]DtmMultiTypeMap{}
+ temp_html_file := os.join_path(dtmi.template_folder, dtm.temp_html_fp)
+ html_mem := dtmi.get_cache(dtm.temp_html_n, temp_html_file, &dtm_placeholers)
+ assert html_mem.len > 10
+}
+
+fn test_return_cache_info_isexistent() {
+ mut dtmi := init_dtm(false, 0)
+ path_template := os.join_path(dtmi.template_folder, dtm.temp_html_fp)
+ lock dtmi.template_caches {
+ dtmi.template_caches << TemplateCache{
+ id: 1
+ path: path_template
+ }
+ }
+ lock dtmi.nbr_of_remaining_template_request {
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 1
+ }
+ }
+ cache_exists, _, _, _, _, _, _, _ := dtmi.return_cache_info_isexistent(path_template)
+ assert cache_exists == true
+ lock dtmi.template_caches {
+ dtmi.template_caches[0].id_redirection = 2
+ dtmi.template_caches << TemplateCache{
+ id: 2
+ path: path_template
+ id_redirection: 3
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 3
+ path: path_template
+ id_redirection: 4
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 4
+ path: path_template
+ id_redirection: 5
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 5
+ path: path_template
+ }
+ }
+ lock dtmi.nbr_of_remaining_template_request {
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 2
+ }
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 3
+ }
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 4
+ }
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 5
+ }
+ }
+ _, id, _, _, _, _, _, _ := dtmi.return_cache_info_isexistent(path_template)
+ assert id == 5
+}
+
+fn test_remaining_template_request() {
+ mut dtmi := init_dtm(false, 0)
+
+ lock dtmi.nbr_of_remaining_template_request {
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 1
+ }
+
+ dtmi.remaining_template_request(true, 1)
+ assert dtmi.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 1
+ dtmi.remaining_template_request(true, 1)
+ assert dtmi.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 2
+ dtmi.remaining_template_request(false, 1)
+ assert dtmi.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 1
+ dtmi.remaining_template_request(false, 1)
+ assert dtmi.nbr_of_remaining_template_request[0].nbr_of_remaining_request == 0
+ }
+}
+
+fn test_check_html_and_placeholders_size() {
+ dtmi := init_dtm(false, 0)
+ temp_html_file := os.join_path(dtmi.template_folder, dtm.temp_html_fp)
+ placeholders := map[string]DtmMultiTypeMap{}
+
+ path, filename := dtmi.check_html_and_placeholders_size(temp_html_file, &placeholders) or {
+ panic(err)
+ }
+
+ assert path.len > 10
+ assert filename.len > 3
+}
+
+fn test_chandler_prevent_cache_duplicate_request() {
+ dtmi := init_dtm(false, 0)
+ temp_html_file := os.join_path(dtmi.template_folder, dtm.temp_html_fp)
+
+ lock dtmi.template_caches {
+ dtmi.template_caches << TemplateCache{
+ id: 1
+ path: temp_html_file
+ cache_request: .new
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 2
+ path: temp_html_file
+ cache_request: .update
+ last_template_mod: i64(1)
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 3
+ path: temp_html_file
+ cache_request: .exp_update
+ last_template_mod: i64(1)
+ generate_at: i64(100)
+ }
+ dtmi.template_caches << TemplateCache{
+ id: 4
+ cache_request: .delete
+ }
+ }
+ new_cache := TemplateCache{
+ id: 5
+ path: temp_html_file
+ cache_request: .new
+ }
+ update_cache := TemplateCache{
+ id: 6
+ path: temp_html_file
+ cache_request: .update
+ last_template_mod: i64(1)
+ }
+ exp_update_cache := TemplateCache{
+ id: 7
+ path: temp_html_file
+ cache_request: .exp_update
+ last_template_mod: i64(1)
+ generate_at: i64(10)
+ cache_delay_expiration: i64(10)
+ }
+ delete_cache := TemplateCache{
+ id: 4
+ cache_request: .delete
+ }
+ mut is_duplicate := dtmi.chandler_prevent_cache_duplicate_request(&new_cache)
+ assert is_duplicate == true
+ is_duplicate = dtmi.chandler_prevent_cache_duplicate_request(&update_cache)
+ assert is_duplicate == true
+ is_duplicate = dtmi.chandler_prevent_cache_duplicate_request(&exp_update_cache)
+ assert is_duplicate == true
+ is_duplicate = dtmi.chandler_prevent_cache_duplicate_request(&delete_cache)
+ assert is_duplicate == false
+
+ lock dtmi.template_caches {
+ dtmi.template_caches.delete(3)
+ }
+
+ is_duplicate = dtmi.chandler_prevent_cache_duplicate_request(&delete_cache)
+ assert is_duplicate == true
+}
+
+fn test_chandler_clear_specific_cache() {
+ mut dtmi := init_dtm(true, 0)
+ defer {
+ dtmi.stop_cache_handler()
+ }
+ dtmi.create_cache()
+ lock dtmi.template_caches {
+ cache_file := os.join_path(dtmi.template_cache_folder, '${dtmi.template_caches[0].name}_${dtmi.template_caches[0].checksum}.cache')
+ index, is_success := dtmi.chandler_clear_specific_cache(dtmi.template_caches[0].id)
+ assert is_success == true
+ assert index == 0
+ cache_exist := os.exists(cache_file)
+ assert cache_exist == false
+ }
+}
+
+fn test_chandler_remaining_cache_template_used() {
+ mut dtmi := init_dtm(false, 0)
+ lock dtmi.nbr_of_remaining_template_request {
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 1
+ nbr_of_remaining_request: 0
+ }
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 2
+ nbr_of_remaining_request: 1
+ need_to_delete: true
+ }
+ dtmi.nbr_of_remaining_template_request << RemainingTemplateRequest{
+ id: 3
+ nbr_of_remaining_request: 0
+ need_to_delete: true
+ }
+ }
+ mut can_delete := dtmi.chandler_remaining_cache_template_used(CacheRequest.update,
+ 3, 3)
+ assert can_delete == true
+ can_delete = dtmi.chandler_remaining_cache_template_used(CacheRequest.update, 2, 2)
+ assert can_delete == false
+ can_delete = dtmi.chandler_remaining_cache_template_used(CacheRequest.delete, 1, 0)
+ assert can_delete == true
+ can_delete = dtmi.chandler_remaining_cache_template_used(CacheRequest.new, 4, 0)
+ assert can_delete == true
+}
+
+fn test_parse_html_file() {
+ mut dtmi := init_dtm(false, 0)
+ temp_folder := os.join_path(dtm.vtmp_dir, dtm.temp_dtm_dir)
+ templates_path := os.join_path(temp_folder, dtm.temp_templates_dir)
+ temp_html_file := os.join_path(templates_path, dtm.temp_html_fp)
+
+ mut placeholders := map[string]DtmMultiTypeMap{}
+
+ is_compressed := true
+ html, content_checksum := dtmi.parse_html_file(temp_html_file, dtm.temp_html_n, &placeholders,
+ is_compressed)
+
+ assert html.len > 0
+ if placeholders.len > 0 {
+ assert content_checksum.len > 0
+ } else {
+ assert content_checksum.len == 0
+ }
+}
+
+fn test_check_if_cache_delay_iscorrect() {
+ check_if_cache_delay_iscorrect(i64(300), dtm.temp_html_n) or { assert false }
+
+ check_if_cache_delay_iscorrect(i64(-100), dtm.temp_html_n) or { assert true }
+}
+
+fn test_cache_request_route() {
+ mut is_cache_exist := true
+ mut cache_delay_expiration := i64(400)
+ mut last_template_mod := get_current_unix_timestamp()
+ mut test_current_template_mod := last_template_mod
+ mut cache_del_exp := 300
+ mut gen_at := last_template_mod
+ mut content_checksum := 'checksumtest1'
+ mut current_content_checksum := 'checksumtest2'
+
+ mut request_type := cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
+ test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
+ content_checksum, current_content_checksum)
+
+ assert request_type == CacheRequest.update
+
+ current_content_checksum = 'checksumtest1'
+
+ request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
+ test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
+ content_checksum, current_content_checksum)
+
+ assert request_type == CacheRequest.cached
+
+ gen_at = (last_template_mod - 500)
+
+ request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
+ test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
+ content_checksum, current_content_checksum)
+
+ assert request_type == CacheRequest.exp_update
+
+ is_cache_exist = false
+
+ request_type = cache_request_route(is_cache_exist, cache_delay_expiration, last_template_mod,
+ test_current_template_mod, cache_del_exp, gen_at, get_current_unix_timestamp(),
+ content_checksum, current_content_checksum)
+
+ assert request_type == CacheRequest.new
+}
+
+fn test_cache_handler() {
+ mut dtmi := init_dtm(true, max_size_data_in_memory)
+ defer {
+ dtmi.stop_cache_handler()
+ }
+ dtmi.create_cache()
+ path_f := os.join_path(dtmi.template_folder, dtm.temp_html_fp)
+ lock dtmi.template_caches {
+ assert dtmi.template_caches[0].id == 1
+ assert dtmi.template_caches[0].name == dtm.temp_html_n
+ assert dtmi.template_caches[0].path == path_f
+ }
+ dtmi.id_to_handlered = 1
+ dtmi.ch_cache_handler <- TemplateCache{
+ id: 1
+ cache_request: .delete
+ }
+ time.sleep(1 * time.millisecond)
+ lock dtmi.template_caches {
+ assert dtmi.template_caches.len == 0
+ }
+}
+
+fn testsuite_end() {
+ temp_folder := os.join_path(dtm.vtmp_dir, dtm.temp_dtm_dir)
+ os.rmdir_all(temp_folder) or {}
+}
+
+// Utilities function :
+
+fn init_dtm(b bool, m int) &DynamicTemplateManager {
+ temp_folder := os.join_path(dtm.vtmp_dir, dtm.temp_dtm_dir)
+ vcache_path := os.join_path(temp_folder, dtm.temp_cache_dir)
+ templates_path := os.join_path(temp_folder, dtm.temp_templates_dir)
+
+ mut dtm := create_dtm()
+
+ init_params := DynamicTemplateManagerInitialisationParams{
+ active_cache_server: b
+ max_size_data_in_mem: m
+ test_cache_dir: vcache_path
+ test_template_dir: templates_path
+ }
+
+ initialize_dtm(mut dtm, init_params) or { panic(err) }
+
+ return dtm
+}
+
+fn (mut tm DynamicTemplateManager) create_cache() string {
+ temp_html_file := os.join_path(tm.template_folder, dtm.temp_html_fp)
+ html_last_mod := os.file_last_mod_unix(temp_html_file)
+ c_time := get_current_unix_timestamp()
+ cache_delay_exp := i64(500)
+ placeholder := map[string]DtmMultiTypeMap{}
+ html := tm.create_template_cache_and_display_html(.new, html_last_mod, c_time, temp_html_file,
+ dtm.temp_html_n, cache_delay_exp, &placeholder)
+ time.sleep(1 * time.millisecond)
+ return html
+}
diff --git a/vlib/x/templating/escape_html_strings_in_templates.v b/vlib/x/templating/escape_html_strings_in_templates.v
new file mode 100644
index 00000000000000..186e09ee456719
--- /dev/null
+++ b/vlib/x/templating/escape_html_strings_in_templates.v
@@ -0,0 +1,11 @@
+module templating
+
+import encoding.html
+
+// Do not delete.
+// Calls to this function are generated by `fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {` in vlib/v/gen/c/str_intp.v,
+// for string interpolation inside vweb templates.
+// TODO: move it to template render
+pub fn filter(s string) string {
+ return html.escape(s)
+}