Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,193 @@
|
||||
module veb
|
||||
|
||||
import os
|
||||
|
||||
pub interface StaticApp {
|
||||
mut:
|
||||
static_files map[string]string
|
||||
static_mime_types map[string]string
|
||||
static_hosts map[string]string
|
||||
static_prefixes []string
|
||||
enable_static_gzip bool
|
||||
enable_static_zstd bool
|
||||
enable_static_compression bool
|
||||
static_compression_max_size int
|
||||
static_compression_mime_types []string
|
||||
enable_markdown_negotiation bool
|
||||
}
|
||||
|
||||
// StaticHandler provides methods to handle static files in your veb App
|
||||
pub struct StaticHandler {
|
||||
pub mut:
|
||||
static_files map[string]string
|
||||
static_mime_types map[string]string
|
||||
static_hosts map[string]string
|
||||
static_prefixes []string
|
||||
// enable_static_gzip enables gzip compression for static files.
|
||||
// Use this for gzip-only compression. For automatic zstd/gzip selection, use enable_static_compression.
|
||||
// Default: false
|
||||
enable_static_gzip bool
|
||||
// enable_static_zstd enables zstd compression for static files.
|
||||
// Use this for zstd-only compression. For automatic zstd/gzip selection, use enable_static_compression.
|
||||
// Default: false
|
||||
enable_static_zstd bool
|
||||
// enable_static_compression enables automatic compression (zstd/gzip) for static files.
|
||||
// When enabled, Veb will choose zstd over gzip when client supports both (better compression ratio).
|
||||
// For gzip-only or zstd-only compression, use enable_static_gzip or enable_static_zstd instead.
|
||||
// Default: false
|
||||
enable_static_compression bool
|
||||
// static_compression_max_size sets the maximum file size in bytes for auto-compression.
|
||||
// Files larger than this threshold will not be auto-compressed.
|
||||
// Manual `.zst`/`.gz` files are still served for allowed MIME types.
|
||||
// Default: 1MB (1024*1024 bytes). Set to 0 to disable auto-compression completely.
|
||||
// Auto-generated cache files are stored in os.cache_dir()/veb/static_compression/.
|
||||
// If that cache directory is not writable, compressed content is served from memory as fallback.
|
||||
static_compression_max_size int = 1048576
|
||||
// static_compression_mime_types limits static compression to the listed MIME types.
|
||||
// Manual `.zst`/`.gz` files and auto-generated compressed cache files are only used for matching types.
|
||||
// Leave empty to preserve the default behavior and allow compression for all static MIME types.
|
||||
static_compression_mime_types []string
|
||||
// enable_markdown_negotiation allows the client sends Accept: text/markdown, then the server will serve .md files, if any.
|
||||
// Default: false (for backward compatibility)
|
||||
enable_markdown_negotiation bool
|
||||
}
|
||||
|
||||
// scan_static_directory recursively scans `directory_path` and returns an error if
|
||||
// no valid MIME type can be found
|
||||
fn (mut sh StaticHandler) scan_static_directory(directory_path string, mount_path string, host string) ! {
|
||||
files := os.ls(directory_path) or { panic(err) }
|
||||
if files.len > 0 {
|
||||
for file in files {
|
||||
full_path := os.join_path(directory_path, file)
|
||||
if os.is_dir(full_path) {
|
||||
sh.scan_static_directory(full_path, mount_path.trim_right('/') + '/' + file, host)!
|
||||
} else if file.contains('.') && !file.starts_with('.') && !file.ends_with('.') {
|
||||
sh.host_serve_static(host, mount_path.trim_right('/') + '/' + file, full_path)!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle_static is used to mark a folder (relative to the current working folder)
|
||||
// as one that contains only static resources (css files, images etc).
|
||||
// If `root` is set the mount path for the dir will be in '/'
|
||||
// Usage:
|
||||
// ```v
|
||||
// os.chdir( os.executable() )?
|
||||
// app.handle_static('assets', true)
|
||||
// ```
|
||||
pub fn (mut sh StaticHandler) handle_static(directory_path string, root bool) !bool {
|
||||
return sh.host_handle_static('', directory_path, root)!
|
||||
}
|
||||
|
||||
// host_handle_static is used to mark a folder (relative to the current working folder)
|
||||
// as one that contains only static resources (css files, images etc).
|
||||
// If `root` is set the mount path for the dir will be in '/'
|
||||
// Usage:
|
||||
// ```v
|
||||
// os.chdir( os.executable() )?
|
||||
// app.host_handle_static('localhost', 'assets', true)
|
||||
// ```
|
||||
pub fn (mut sh StaticHandler) host_handle_static(host string, directory_path string, root bool) !bool {
|
||||
if !os.exists(directory_path) {
|
||||
return error('directory `${directory_path}` does not exist. The directory should be relative to the current working directory: ${os.getwd()}')
|
||||
}
|
||||
dir_path := directory_path.trim_space().trim_right('/')
|
||||
mut mount_path := ''
|
||||
if dir_path != '.' && os.is_dir(dir_path) && !root {
|
||||
// Mount point hygiene, "./assets" => "/assets".
|
||||
mount_path = '/' + dir_path.trim_left('.').trim('/')
|
||||
}
|
||||
sh.scan_static_directory(dir_path, mount_path, host)!
|
||||
return true
|
||||
}
|
||||
|
||||
// mount_static_folder_at - makes all static files in `directory_path` and inside it, available at http://server/mount_path
|
||||
// For example: suppose you have called .mount_static_folder_at('/var/share/myassets', '/assets'),
|
||||
// and you have a file /var/share/myassets/main.css .
|
||||
// => That file will be available at URL: http://server/assets/main.css .
|
||||
pub fn (mut sh StaticHandler) mount_static_folder_at(directory_path string, mount_path string) !bool {
|
||||
return sh.host_mount_static_folder_at('', directory_path, mount_path)!
|
||||
}
|
||||
|
||||
// host_mount_static_folder_at - makes all static files in `directory_path` and inside it, available at http://host/mount_path
|
||||
// For example: suppose you have called .host_mount_static_folder_at('localhost', '/var/share/myassets', '/assets'),
|
||||
// and you have a file /var/share/myassets/main.css .
|
||||
// => That file will be available at URL: http://localhost/assets/main.css .
|
||||
pub fn (mut sh StaticHandler) host_mount_static_folder_at(host string, directory_path string, mount_path string) !bool {
|
||||
if mount_path == '' || mount_path[0] != `/` {
|
||||
return error('invalid mount path! The path should start with `/`')
|
||||
} else if !os.exists(directory_path) {
|
||||
return error('directory `${directory_path}` does not exist. The directory should be relative to the current working directory: ${os.getwd()}')
|
||||
}
|
||||
|
||||
dir_path := directory_path.trim_right('/')
|
||||
|
||||
trim_mount_path := mount_path.trim_left('/').trim_right('/')
|
||||
sh.scan_static_directory(dir_path, '/${trim_mount_path}', host)!
|
||||
return true
|
||||
}
|
||||
|
||||
// Serves a file static
|
||||
// `url` is the access path on the site, `file_path` is the real path to the file, `mime_type` is the file type
|
||||
pub fn (mut sh StaticHandler) serve_static(url string, file_path string) ! {
|
||||
sh.host_serve_static('', url, file_path)!
|
||||
}
|
||||
|
||||
// Serves a file static
|
||||
// `url` is the access path on the site, `file_path` is the real path to the file
|
||||
// `host` is the host to serve the file from
|
||||
pub fn (mut sh StaticHandler) host_serve_static(host string, url string, file_path string) ! {
|
||||
ext := os.file_ext(file_path).to_lower()
|
||||
|
||||
// Rudimentary guard against adding files not in mime_types.
|
||||
if ext !in sh.static_mime_types && ext !in mime_types {
|
||||
return error('unknown MIME type for file extension "${ext}". You can register your MIME type in `app.static_mime_types`')
|
||||
}
|
||||
sh.static_files[url] = file_path
|
||||
sh.static_hosts[url] = host
|
||||
sh.register_static_prefix(url)
|
||||
}
|
||||
|
||||
fn static_prefix_for_url(url string) string {
|
||||
if url.len == 0 || url[0] != `/` {
|
||||
return url
|
||||
}
|
||||
mut slash_count := 0
|
||||
for i in 0 .. url.len {
|
||||
if url[i] == `/` {
|
||||
slash_count++
|
||||
if slash_count == 2 {
|
||||
return url[..i + 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
fn (mut sh StaticHandler) register_static_prefix(url string) {
|
||||
prefix := static_prefix_for_url(url)
|
||||
if prefix !in sh.static_prefixes {
|
||||
sh.static_prefixes << prefix
|
||||
}
|
||||
}
|
||||
|
||||
fn app_static_handler[A](app &A) StaticHandler {
|
||||
$if A is $struct {
|
||||
$for field in A.fields {
|
||||
$if field.is_embed {
|
||||
$if field.name == 'StaticHandler' {
|
||||
return app.$(field.name)
|
||||
} $else $if field.typ is $struct {
|
||||
return app_static_handler(app.$(field.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return StaticHandler{
|
||||
static_files: map[string]string{}
|
||||
static_mime_types: map[string]string{}
|
||||
static_hosts: map[string]string{}
|
||||
static_prefixes: []string{}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user