vweb: add handle static root & documentation (#8865)

pull/8840/head^2
Louis Schmieder 2021-02-21 19:01:29 +01:00 committed by GitHub
parent 0ccd9f9c6e
commit 7a35131721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 8 deletions

View File

@ -15,7 +15,7 @@ fn main() {
pub fn (mut app App) init_once() { pub fn (mut app App) init_once() {
app.serve_static('/favicon.ico', 'favicon.ico', 'img/x-icon') app.serve_static('/favicon.ico', 'favicon.ico', 'img/x-icon')
app.handle_static('.') app.handle_static('.', false)
} }
pub fn (mut app App) index() vweb.Result { pub fn (mut app App) index() vweb.Result {

View File

@ -23,7 +23,7 @@ pub fn (mut app App) init_once() {
// app.handle_static('assets') // app.handle_static('assets')
// This would make available all known static mime types from current // This would make available all known static mime types from current
// directory and below. // directory and below.
app.handle_static('.') app.handle_static('.', false)
} }
pub fn (mut app App) init() { pub fn (mut app App) init() {

View File

@ -18,7 +18,7 @@ fn main() {
} }
pub fn (mut app App) init_once() { pub fn (mut app App) init_once() {
app.handle_static('.') app.handle_static('.', false)
} }
pub fn (mut app App) json_endpoint() vweb.Result { pub fn (mut app App) json_endpoint() vweb.Result {

View File

@ -74,9 +74,6 @@ pub fn (ctx Context) init_once() {}
// declaring init in your App struct is optional // declaring init in your App struct is optional
pub fn (ctx Context) init() {} pub fn (ctx Context) init() {}
// declaring uninit in your App struct is optional
pub fn (ctx Context) uninit() {}
pub struct Cookie { pub struct Cookie {
name string name string
value string value string
@ -89,6 +86,7 @@ pub struct Cookie {
pub struct Result { pub struct Result {
} }
// vweb intern function
pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bool { pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bool {
if ctx.done { if ctx.done {
return false return false
@ -138,26 +136,31 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo
return true return true
} }
// Response HTTP_OK with s as payload with content-type `text/html`
pub fn (mut ctx Context) html(s string) Result { pub fn (mut ctx Context) html(s string) Result {
ctx.send_response_to_client('text/html', s) ctx.send_response_to_client('text/html', s)
return Result{} return Result{}
} }
// Response HTTP_OK with s as payload with content-type `text/plain`
pub fn (mut ctx Context) text(s string) Result { pub fn (mut ctx Context) text(s string) Result {
ctx.send_response_to_client('text/plain', s) ctx.send_response_to_client('text/plain', s)
return Result{} return Result{}
} }
// Response HTTP_OK with s as payload with content-type `application/json`
pub fn (mut ctx Context) json(s string) Result { pub fn (mut ctx Context) json(s string) Result {
ctx.send_response_to_client('application/json', s) ctx.send_response_to_client('application/json', s)
return Result{} return Result{}
} }
// Response HTTP_OK with s as payload
pub fn (mut ctx Context) ok(s string) Result { pub fn (mut ctx Context) ok(s string) Result {
ctx.send_response_to_client(ctx.content_type, s) ctx.send_response_to_client(ctx.content_type, s)
return Result{} return Result{}
} }
// Response a server error
pub fn (mut ctx Context) server_error(ecode int) Result { pub fn (mut ctx Context) server_error(ecode int) Result {
$if debug { $if debug {
eprintln('> ctx.server_error ecode: $ecode') eprintln('> ctx.server_error ecode: $ecode')
@ -169,6 +172,7 @@ pub fn (mut ctx Context) server_error(ecode int) Result {
return Result{} return Result{}
} }
// Redirect to an url
pub fn (mut ctx Context) redirect(url string) Result { pub fn (mut ctx Context) redirect(url string) Result {
if ctx.done { if ctx.done {
return Result{} return Result{}
@ -180,6 +184,7 @@ pub fn (mut ctx Context) redirect(url string) Result {
return Result{} return Result{}
} }
// Send an not_found response
pub fn (mut ctx Context) not_found() Result { pub fn (mut ctx Context) not_found() Result {
if ctx.done { if ctx.done {
return Result{} return Result{}
@ -189,11 +194,13 @@ pub fn (mut ctx Context) not_found() Result {
return Result{} return Result{}
} }
// Enables chunk transfer with max_chunk_len per chunk
pub fn (mut ctx Context) enable_chunked_transfer(max_chunk_len int) { pub fn (mut ctx Context) enable_chunked_transfer(max_chunk_len int) {
ctx.chunked_transfer = true ctx.chunked_transfer = true
ctx.max_chunk_len = max_chunk_len ctx.max_chunk_len = max_chunk_len
} }
// Sets a cookie
pub fn (mut ctx Context) set_cookie(cookie Cookie) { pub fn (mut ctx Context) set_cookie(cookie Cookie) {
mut cookie_data := []string{} mut cookie_data := []string{}
mut secure := if cookie.secure { 'Secure;' } else { '' } mut secure := if cookie.secure { 'Secure;' } else { '' }
@ -206,20 +213,25 @@ pub fn (mut ctx Context) set_cookie(cookie Cookie) {
ctx.add_header('Set-Cookie', '$cookie.name=$cookie.value; $data') ctx.add_header('Set-Cookie', '$cookie.name=$cookie.value; $data')
} }
// Old function
[deprecated]
pub fn (mut ctx Context) set_cookie_old(key string, val string) { pub fn (mut ctx Context) set_cookie_old(key string, val string) {
// TODO support directives, escape cookie value (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) // TODO support directives, escape cookie value (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
// ctx.add_header('Set-Cookie', '${key}=${val}; Secure; HttpOnly') // ctx.add_header('Set-Cookie', '${key}=${val}; Secure; HttpOnly')
ctx.add_header('Set-Cookie', '$key=$val; HttpOnly') ctx.add_header('Set-Cookie', '$key=$val; HttpOnly')
} }
// Sets the response content type
pub fn (mut ctx Context) set_content_type(typ string) { pub fn (mut ctx Context) set_content_type(typ string) {
ctx.content_type = typ ctx.content_type = typ
} }
// Sets a cookie with a `expire_data`
pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, expire_date time.Time) { pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, expire_date time.Time) {
ctx.add_header('Set-Cookie', '$key=$val; Secure; HttpOnly; expires=$expire_date.utc_string()') ctx.add_header('Set-Cookie', '$key=$val; Secure; HttpOnly; expires=$expire_date.utc_string()')
} }
// Gets a cookie by a key
pub fn (ctx &Context) get_cookie(key string) ?string { // TODO refactor pub fn (ctx &Context) get_cookie(key string) ?string { // TODO refactor
mut cookie_header := ctx.get_header('cookie') mut cookie_header := ctx.get_header('cookie')
if cookie_header == '' { if cookie_header == '' {
@ -239,6 +251,7 @@ pub fn (ctx &Context) get_cookie(key string) ?string { // TODO refactor
return error('Cookie not found') return error('Cookie not found')
} }
// Sets the response status
pub fn (mut ctx Context) set_status(code int, desc string) { pub fn (mut ctx Context) set_status(code int, desc string) {
if code < 100 || code > 599 { if code < 100 || code > 599 {
ctx.status = '500 Internal Server Error' ctx.status = '500 Internal Server Error'
@ -247,12 +260,14 @@ pub fn (mut ctx Context) set_status(code int, desc string) {
} }
} }
// Adds an header to the response with key and val
pub fn (mut ctx Context) add_header(key string, val string) { pub fn (mut ctx Context) add_header(key string, val string) {
// println('add_header($key, $val)') // println('add_header($key, $val)')
ctx.headers = ctx.headers + '\r\n$key: $val' ctx.headers = ctx.headers + '\r\n$key: $val'
// println(ctx.headers) // println(ctx.headers)
} }
// Returns the header data from the key
pub fn (ctx &Context) get_header(key string) string { pub fn (ctx &Context) get_header(key string) string {
return ctx.req.headers[key] return ctx.req.headers[key]
} }
@ -615,6 +630,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
} }
} }
// vweb intern function
pub fn (mut ctx Context) parse_form(s string) { pub fn (mut ctx Context) parse_form(s string) {
if ctx.req.method !in vweb.methods_with_form { if ctx.req.method !in vweb.methods_with_form {
return return
@ -644,6 +660,7 @@ pub fn (mut ctx Context) parse_form(s string) {
// ... // ...
} }
// vweb intern function
[manualfree] [manualfree]
pub fn (mut ctx Context) parse_multipart_form(s string, b string) { pub fn (mut ctx Context) parse_multipart_form(s string, b string) {
if ctx.req.method !in vweb.methods_with_form { if ctx.req.method !in vweb.methods_with_form {
@ -712,13 +729,15 @@ fn (mut ctx Context) scan_static_directory(directory_path string, mount_path str
} }
} }
pub fn (mut ctx Context) handle_static(directory_path string) bool { // Handles a directory static
// If `root` is set the mount path for the dir will be in '/'
pub fn (mut ctx Context) handle_static(directory_path string, root bool) bool {
if ctx.done || !os.exists(directory_path) { if ctx.done || !os.exists(directory_path) {
return false return false
} }
dir_path := directory_path.trim_space().trim_right('/') dir_path := directory_path.trim_space().trim_right('/')
mut mount_path := '' mut mount_path := ''
if dir_path != '.' && os.is_dir(dir_path) { if dir_path != '.' && os.is_dir(dir_path) && !root {
// Mount point hygene, "./assets" => "/assets". // Mount point hygene, "./assets" => "/assets".
mount_path = '/' + dir_path.trim_left('.').trim('/') mount_path = '/' + dir_path.trim_left('.').trim('/')
} }
@ -726,11 +745,14 @@ pub fn (mut ctx Context) handle_static(directory_path string) bool {
return true 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 ctx Context) serve_static(url string, file_path string, mime_type string) { pub fn (mut ctx Context) serve_static(url string, file_path string, mime_type string) {
ctx.static_files[url] = file_path ctx.static_files[url] = file_path
ctx.static_mime_types[url] = mime_type ctx.static_mime_types[url] = mime_type
} }
// Returns the ip address from the current user
pub fn (ctx &Context) ip() string { pub fn (ctx &Context) ip() string {
mut ip := ctx.req.headers['X-Forwarded-For'] mut ip := ctx.req.headers['X-Forwarded-For']
if ip == '' { if ip == '' {
@ -745,6 +767,7 @@ pub fn (ctx &Context) ip() string {
return ip return ip
} }
// Set s to the form error
pub fn (mut ctx Context) error(s string) { pub fn (mut ctx Context) error(s string) {
ctx.form_error = s ctx.form_error = s
} }
@ -770,6 +793,7 @@ fn strip(s string) string {
return s.trim('\r\n') return s.trim('\r\n')
} }
// Returns an empty result
pub fn not_found() Result { pub fn not_found() Result {
return Result{} return Result{}
} }
@ -785,6 +809,7 @@ fn filter(s string) string {
]) ])
} }
// A type which don't get filtered inside templates
pub type RawHtml = string pub type RawHtml = string
fn send_string(mut conn net.TcpConn, s string) ? { fn send_string(mut conn net.TcpConn, s string) ? {