refactor: Migrate from vweb to veb web framework
- Update all references from `vweb` to `veb` - Add `veb.StaticHandler` to `Playground` struct - Ensure error propagation for static file serving calls - Apply consistent indentation across various module definitions - Adjust documentation and comments for `veb` framework
This commit is contained in:
@@ -1,26 +1,26 @@
|
|||||||
module net
|
module net
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
`net` provides networking functions. It is mostly a wrapper to BSD sockets, so you can listen on a port, connect to remote TCP/UDP services, and communicate with them.
|
`net` provides networking functions. It is mostly a wrapper to BSD sockets, so you can listen on a port, connect to remote TCP/UDP services, and communicate with them.
|
||||||
|
|
||||||
const msg_nosignal = 0x4000
|
const msg_nosignal = 0x4000
|
||||||
const err_connection_refused = error_with_code('net: connection refused', errors_base + 10)
|
const err_connection_refused = error_with_code('net: connection refused', errors_base + 10)
|
||||||
const err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
|
const err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
|
||||||
errors_base + 3)
|
errors_base + 3)
|
||||||
const opts_can_set = [
|
const opts_can_set = [
|
||||||
SocketOption.broadcast,
|
SocketOption.broadcast,
|
||||||
.debug,
|
.debug,
|
||||||
.dont_route,
|
.dont_route,
|
||||||
.keep_alive,
|
.keep_alive,
|
||||||
.linger,
|
.linger,
|
||||||
.oob_inline,
|
.oob_inline,
|
||||||
.receive_buf_size,
|
.receive_buf_size,
|
||||||
.receive_low_size,
|
.receive_low_size,
|
||||||
.receive_timeout,
|
.receive_timeout,
|
||||||
.send_buf_size,
|
.send_buf_size,
|
||||||
.send_low_size,
|
.send_low_size,
|
||||||
.send_timeout,
|
.send_timeout,
|
||||||
.ipv6_only,
|
.ipv6_only,
|
||||||
]
|
]
|
||||||
const error_eagain = C.EAGAIN
|
const error_eagain = C.EAGAIN
|
||||||
const err_port_out_of_range = error_with_code('net: port out of range', errors_base + 5)
|
const err_port_out_of_range = error_with_code('net: port out of range', errors_base + 5)
|
||||||
@@ -29,12 +29,12 @@ const err_connect_failed = error_with_code('net: connect failed', errors_base +
|
|||||||
const errors_base = 0
|
const errors_base = 0
|
||||||
Well defined errors that are returned from socket functions
|
Well defined errors that are returned from socket functions
|
||||||
const opts_int = [
|
const opts_int = [
|
||||||
SocketOption.receive_buf_size,
|
SocketOption.receive_buf_size,
|
||||||
.receive_low_size,
|
.receive_low_size,
|
||||||
.receive_timeout,
|
.receive_timeout,
|
||||||
.send_buf_size,
|
.send_buf_size,
|
||||||
.send_low_size,
|
.send_low_size,
|
||||||
.send_timeout,
|
.send_timeout,
|
||||||
]
|
]
|
||||||
const error_eintr = C.EINTR
|
const error_eintr = C.EINTR
|
||||||
const error_ewouldblock = C.EWOULDBLOCK
|
const error_ewouldblock = C.EWOULDBLOCK
|
||||||
@@ -43,17 +43,17 @@ const error_einprogress = C.EINPROGRESS
|
|||||||
const err_timed_out_code = errors_base + 9
|
const err_timed_out_code = errors_base + 9
|
||||||
const err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8)
|
const err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8)
|
||||||
const err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
|
const err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
|
||||||
errors_base + 1)
|
errors_base + 1)
|
||||||
const msg_dontwait = C.MSG_DONTWAIT
|
const msg_dontwait = C.MSG_DONTWAIT
|
||||||
const infinite_timeout = time.infinite
|
const infinite_timeout = time.infinite
|
||||||
infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions only ever return with data)
|
infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions only ever return with data)
|
||||||
const no_timeout = time.Duration(0)
|
const no_timeout = time.Duration(0)
|
||||||
no_timeout should be given to functions when no timeout is wanted (i.e. all functions return instantly)
|
no_timeout should be given to functions when no timeout is wanted (i.e. all functions return instantly)
|
||||||
const err_timed_out = error_with_code('net: op timed out', errors_base + 9)
|
const err_timed_out = error_with_code('net: op timed out', errors_base + 9)
|
||||||
const tcp_default_read_timeout = 30 * time.second
|
const tcp_default_read_timeout = 30 *time.second
|
||||||
const err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
|
const err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
|
||||||
errors_base + 2)
|
errors_base + 2)
|
||||||
const tcp_default_write_timeout = 30 * time.second
|
const tcp_default_write_timeout = 30* time.second
|
||||||
fn addr_from_socket_handle(handle int) Addr
|
fn addr_from_socket_handle(handle int) Addr
|
||||||
addr_from_socket_handle returns an address, based on the given integer socket `handle`
|
addr_from_socket_handle returns an address, based on the given integer socket `handle`
|
||||||
fn close(handle int) !
|
fn close(handle int) !
|
||||||
@@ -94,16 +94,16 @@ fn validate_port(port int) !u16
|
|||||||
validate_port checks whether a port is valid and returns the port or an error
|
validate_port checks whether a port is valid and returns the port or an error
|
||||||
fn wrap_error(error_code int) !
|
fn wrap_error(error_code int) !
|
||||||
interface Connection {
|
interface Connection {
|
||||||
addr() !Addr
|
addr() !Addr
|
||||||
peer_addr() !Addr
|
peer_addr() !Addr
|
||||||
mut:
|
mut:
|
||||||
read(mut []u8) !int
|
read(mut []u8) !int
|
||||||
write([]u8) !int
|
write([]u8) !int
|
||||||
close() !
|
close() !
|
||||||
}
|
}
|
||||||
Connection provides a generic SOCK_STREAM style interface that protocols can use as a base connection object to support TCP, UNIX Domain Sockets and various proxying solutions.
|
Connection provides a generic SOCK_STREAM style interface that protocols can use as a base connection object to support TCP, UNIX Domain Sockets and various proxying solutions.
|
||||||
interface Dialer {
|
interface Dialer {
|
||||||
dial(address string) !Connection
|
dial(address string) !Connection
|
||||||
}
|
}
|
||||||
Dialer is an abstract dialer interface for producing connections to adresses.
|
Dialer is an abstract dialer interface for producing connections to adresses.
|
||||||
fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) !
|
fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) !
|
||||||
@@ -114,49 +114,49 @@ fn (mut s TcpSocket) bind(addr string) !
|
|||||||
fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) !
|
fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) !
|
||||||
fn (mut s UdpSocket) set_dualstack(on bool) !
|
fn (mut s UdpSocket) set_dualstack(on bool) !
|
||||||
enum AddrFamily {
|
enum AddrFamily {
|
||||||
unix = C.AF_UNIX
|
unix = C.AF_UNIX
|
||||||
ip = C.AF_INET
|
ip = C.AF_INET
|
||||||
ip6 = C.AF_INET6
|
ip6 = C.AF_INET6
|
||||||
unspec = C.AF_UNSPEC
|
unspec = C.AF_UNSPEC
|
||||||
}
|
}
|
||||||
AddrFamily are the available address families
|
AddrFamily are the available address families
|
||||||
enum ShutdownDirection {
|
enum ShutdownDirection {
|
||||||
read
|
read
|
||||||
write
|
write
|
||||||
read_and_write
|
read_and_write
|
||||||
}
|
}
|
||||||
ShutdownDirection is used by `net.shutdown`, for specifying the direction for which the communication will be cut.
|
ShutdownDirection is used by `net.shutdown`, for specifying the direction for which the communication will be cut.
|
||||||
enum SocketOption {
|
enum SocketOption {
|
||||||
// TODO: SO_ACCEPT_CONN is not here because windows doesn't support it
|
// TODO: SO_ACCEPT_CONN is not here because windows doesn't support it
|
||||||
// and there is no easy way to define it
|
// and there is no easy way to define it
|
||||||
broadcast = C.SO_BROADCAST
|
broadcast = C.SO_BROADCAST
|
||||||
debug = C.SO_DEBUG
|
debug = C.SO_DEBUG
|
||||||
dont_route = C.SO_DONTROUTE
|
dont_route = C.SO_DONTROUTE
|
||||||
error = C.SO_ERROR
|
error = C.SO_ERROR
|
||||||
keep_alive = C.SO_KEEPALIVE
|
keep_alive = C.SO_KEEPALIVE
|
||||||
linger = C.SO_LINGER
|
linger = C.SO_LINGER
|
||||||
oob_inline = C.SO_OOBINLINE
|
oob_inline = C.SO_OOBINLINE
|
||||||
reuse_addr = C.SO_REUSEADDR
|
reuse_addr = C.SO_REUSEADDR
|
||||||
receive_buf_size = C.SO_RCVBUF
|
receive_buf_size = C.SO_RCVBUF
|
||||||
receive_low_size = C.SO_RCVLOWAT
|
receive_low_size = C.SO_RCVLOWAT
|
||||||
receive_timeout = C.SO_RCVTIMEO
|
receive_timeout = C.SO_RCVTIMEO
|
||||||
send_buf_size = C.SO_SNDBUF
|
send_buf_size = C.SO_SNDBUF
|
||||||
send_low_size = C.SO_SNDLOWAT
|
send_low_size = C.SO_SNDLOWAT
|
||||||
send_timeout = C.SO_SNDTIMEO
|
send_timeout = C.SO_SNDTIMEO
|
||||||
socket_type = C.SO_TYPE
|
socket_type = C.SO_TYPE
|
||||||
ipv6_only = C.IPV6_V6ONLY
|
ipv6_only = C.IPV6_V6ONLY
|
||||||
}
|
}
|
||||||
enum SocketType {
|
enum SocketType {
|
||||||
udp = C.SOCK_DGRAM
|
udp = C.SOCK_DGRAM
|
||||||
tcp = C.SOCK_STREAM
|
tcp = C.SOCK_STREAM
|
||||||
seqpacket = C.SOCK_SEQPACKET
|
seqpacket = C.SOCK_SEQPACKET
|
||||||
}
|
}
|
||||||
SocketType are the available sockets
|
SocketType are the available sockets
|
||||||
struct Addr {
|
struct Addr {
|
||||||
pub:
|
pub:
|
||||||
len u8
|
len u8
|
||||||
f u8
|
f u8
|
||||||
addr AddrData
|
addr AddrData
|
||||||
}
|
}
|
||||||
fn (a Addr) family() AddrFamily
|
fn (a Addr) family() AddrFamily
|
||||||
family returns the family/kind of the given address `a`
|
family returns the family/kind of the given address `a`
|
||||||
@@ -168,72 +168,72 @@ fn (a Addr) str() string
|
|||||||
str returns a string representation of the address `a`
|
str returns a string representation of the address `a`
|
||||||
struct C.addrinfo {
|
struct C.addrinfo {
|
||||||
mut:
|
mut:
|
||||||
ai_family int
|
ai_family int
|
||||||
ai_socktype int
|
ai_socktype int
|
||||||
ai_flags int
|
ai_flags int
|
||||||
ai_protocol int
|
ai_protocol int
|
||||||
ai_addrlen int
|
ai_addrlen int
|
||||||
ai_addr voidptr
|
ai_addr voidptr
|
||||||
ai_canonname voidptr
|
ai_canonname voidptr
|
||||||
ai_next voidptr
|
ai_next voidptr
|
||||||
}
|
}
|
||||||
struct C.fd_set {}
|
struct C.fd_set {}
|
||||||
struct C.sockaddr_in {
|
struct C.sockaddr_in {
|
||||||
mut:
|
mut:
|
||||||
sin_len u8
|
sin_len u8
|
||||||
sin_family u8
|
sin_family u8
|
||||||
sin_port u16
|
sin_port u16
|
||||||
sin_addr u32
|
sin_addr u32
|
||||||
sin_zero [8]char
|
sin_zero [8]char
|
||||||
}
|
}
|
||||||
struct C.sockaddr_in6 {
|
struct C.sockaddr_in6 {
|
||||||
mut:
|
mut:
|
||||||
// 1 + 1 + 2 + 4 + 16 + 4 = 28;
|
// 1 + 1 + 2 + 4 + 16 + 4 = 28;
|
||||||
sin6_len u8 // 1
|
sin6_len u8 // 1
|
||||||
sin6_family u8 // 1
|
sin6_family u8 // 1
|
||||||
sin6_port u16 // 2
|
sin6_port u16 // 2
|
||||||
sin6_flowinfo u32 // 4
|
sin6_flowinfo u32 // 4
|
||||||
sin6_addr [16]u8 // 16
|
sin6_addr [16]u8 // 16
|
||||||
sin6_scope_id u32 // 4
|
sin6_scope_id u32 // 4
|
||||||
}
|
}
|
||||||
struct C.sockaddr_un {
|
struct C.sockaddr_un {
|
||||||
mut:
|
mut:
|
||||||
sun_len u8
|
sun_len u8
|
||||||
sun_family u8
|
sun_family u8
|
||||||
sun_path [max_unix_path]char
|
sun_path [max_unix_path]char
|
||||||
}
|
}
|
||||||
struct Ip {
|
struct Ip {
|
||||||
port u16
|
port u16
|
||||||
addr [4]u8
|
addr [4]u8
|
||||||
// Pad to size so that socket functions
|
// Pad to size so that socket functions
|
||||||
// dont complain to us (see in.h and bind())
|
// dont complain to us (see in.h and bind())
|
||||||
// TODO(emily): I would really like to use
|
// TODO(emily): I would really like to use
|
||||||
// some constant calculations here
|
// some constant calculations here
|
||||||
// so that this doesnt have to be hardcoded
|
// so that this doesnt have to be hardcoded
|
||||||
sin_pad [8]u8
|
sin_pad [8]u8
|
||||||
}
|
}
|
||||||
fn (a Ip) str() string
|
fn (a Ip) str() string
|
||||||
str returns a string representation of `a`
|
str returns a string representation of `a`
|
||||||
struct Ip6 {
|
struct Ip6 {
|
||||||
port u16
|
port u16
|
||||||
flow_info u32
|
flow_info u32
|
||||||
addr [16]u8
|
addr [16]u8
|
||||||
scope_id u32
|
scope_id u32
|
||||||
}
|
}
|
||||||
fn (a Ip6) str() string
|
fn (a Ip6) str() string
|
||||||
str returns a string representation of `a`
|
str returns a string representation of `a`
|
||||||
struct ListenOptions {
|
struct ListenOptions {
|
||||||
pub:
|
pub:
|
||||||
dualstack bool = true
|
dualstack bool = true
|
||||||
backlog int = 128
|
backlog int = 128
|
||||||
}
|
}
|
||||||
struct ShutdownConfig {
|
struct ShutdownConfig {
|
||||||
pub:
|
pub:
|
||||||
how ShutdownDirection = .read_and_write
|
how ShutdownDirection = .read_and_write
|
||||||
}
|
}
|
||||||
struct Socket {
|
struct Socket {
|
||||||
pub:
|
pub:
|
||||||
handle int
|
handle int
|
||||||
}
|
}
|
||||||
fn (s &Socket) address() !Addr
|
fn (s &Socket) address() !Addr
|
||||||
address gets the address of a socket
|
address gets the address of a socket
|
||||||
@@ -243,13 +243,13 @@ fn (t TCPDialer) dial(address string) !Connection
|
|||||||
dial will try to create a new abstract connection to the given address. It will return an error, if that is not possible.
|
dial will try to create a new abstract connection to the given address. It will return an error, if that is not possible.
|
||||||
struct TcpConn {
|
struct TcpConn {
|
||||||
pub mut:
|
pub mut:
|
||||||
sock TcpSocket
|
sock TcpSocket
|
||||||
handle int
|
handle int
|
||||||
write_deadline time.Time
|
write_deadline time.Time
|
||||||
read_deadline time.Time
|
read_deadline time.Time
|
||||||
read_timeout time.Duration
|
read_timeout time.Duration
|
||||||
write_timeout time.Duration
|
write_timeout time.Duration
|
||||||
is_blocking bool = true
|
is_blocking bool = true
|
||||||
}
|
}
|
||||||
fn (c &TcpConn) addr() !Addr
|
fn (c &TcpConn) addr() !Addr
|
||||||
fn (mut c TcpConn) close() !
|
fn (mut c TcpConn) close() !
|
||||||
@@ -265,7 +265,7 @@ fn (c TcpConn) read(mut buf []u8) !int
|
|||||||
fn (mut c TcpConn) read_deadline() !time.Time
|
fn (mut c TcpConn) read_deadline() !time.Time
|
||||||
fn (mut con TcpConn) read_line() string
|
fn (mut con TcpConn) read_line() string
|
||||||
read_line is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, or just '', on EOF.
|
read_line is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, or just '', on EOF.
|
||||||
|
|
||||||
Note: if you want more control over the buffer, please use a buffered IO reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})`
|
Note: if you want more control over the buffer, please use a buffered IO reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})`
|
||||||
fn (mut con TcpConn) read_line_max(max_line_len int) string
|
fn (mut con TcpConn) read_line_max(max_line_len int) string
|
||||||
read_line_max is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, '' on EOF. It stops reading, when the result line length exceeds max_line_len.
|
read_line_max is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, '' on EOF. It stops reading, when the result line length exceeds max_line_len.
|
||||||
@@ -278,7 +278,7 @@ fn (mut c TcpConn) set_read_deadline(deadline time.Time)
|
|||||||
fn (mut c TcpConn) set_read_timeout(t time.Duration)
|
fn (mut c TcpConn) set_read_timeout(t time.Duration)
|
||||||
fn (mut c TcpConn) set_sock() !
|
fn (mut c TcpConn) set_sock() !
|
||||||
set_sock initialises the c.sock field. It should be called after `.accept_only()!`.
|
set_sock initialises the c.sock field. It should be called after `.accept_only()!`.
|
||||||
|
|
||||||
Note: just use `.accept()!`. In most cases it is simpler, and calls `.set_sock()!` for you.
|
Note: just use `.accept()!`. In most cases it is simpler, and calls `.set_sock()!` for you.
|
||||||
fn (mut c TcpConn) set_write_deadline(deadline time.Time)
|
fn (mut c TcpConn) set_write_deadline(deadline time.Time)
|
||||||
fn (mut c TcpConn) set_write_timeout(t time.Duration)
|
fn (mut c TcpConn) set_write_timeout(t time.Duration)
|
||||||
@@ -295,19 +295,17 @@ fn (mut c TcpConn) write_string(s string) !int
|
|||||||
fn (c &TcpConn) write_timeout() time.Duration
|
fn (c &TcpConn) write_timeout() time.Duration
|
||||||
struct TcpListener {
|
struct TcpListener {
|
||||||
pub mut:
|
pub mut:
|
||||||
sock TcpSocket
|
sock TcpSocket
|
||||||
accept_timeout time.Duration
|
accept_timeout time.Duration
|
||||||
accept_deadline time.Time
|
accept_deadline time.Time
|
||||||
is_blocking bool = true
|
is_blocking bool = true
|
||||||
}
|
}
|
||||||
fn (mut l TcpListener) accept() !&TcpConn
|
fn (mut l TcpListener) accept() !&TcpConn
|
||||||
accept a tcp connection from an external source to the listener `l`.
|
accept a tcp connection from an external source to the listener `l`.
|
||||||
fn (mut l TcpListener) accept_only() !&TcpConn
|
fn (mut l TcpListener) accept_only() !&TcpConn
|
||||||
accept_only accepts a tcp connection from an external source to the listener `l`. Unlike `accept`, `accept_only` *will not call* `.set_sock()!` on the result, and is thus faster.
|
accept_only accepts a tcp connection from an external source to the listener `l`. Unlike `accept`, `accept_only` *will not call* `.set_sock()!` on the result, and is thus faster.
|
||||||
|
|
||||||
|
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/veb/veb.v .
|
||||||
|
|
||||||
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/vweb/vweb.v .
|
|
||||||
|
|
||||||
If you do not need that, just call `.accept()!` instead, which will call `.set_sock()!` for you.
|
If you do not need that, just call `.accept()!` instead, which will call `.set_sock()!` for you.
|
||||||
fn (c &TcpListener) accept_deadline() !time.Time
|
fn (c &TcpListener) accept_deadline() !time.Time
|
||||||
@@ -319,12 +317,12 @@ fn (mut c TcpListener) close() !
|
|||||||
fn (c &TcpListener) addr() !Addr
|
fn (c &TcpListener) addr() !Addr
|
||||||
struct UdpConn {
|
struct UdpConn {
|
||||||
pub mut:
|
pub mut:
|
||||||
sock UdpSocket
|
sock UdpSocket
|
||||||
mut:
|
mut:
|
||||||
write_deadline time.Time
|
write_deadline time.Time
|
||||||
read_deadline time.Time
|
read_deadline time.Time
|
||||||
read_timeout time.Duration
|
read_timeout time.Duration
|
||||||
write_timeout time.Duration
|
write_timeout time.Duration
|
||||||
}
|
}
|
||||||
fn (mut c UdpConn) write_ptr(b &u8, len int) !int
|
fn (mut c UdpConn) write_ptr(b &u8, len int) !int
|
||||||
sock := UdpSocket{ handle: sbase.handle l: local r: resolve_wrapper(raddr) } }
|
sock := UdpSocket{ handle: sbase.handle l: local r: resolve_wrapper(raddr) } }
|
||||||
@@ -350,5 +348,5 @@ fn (mut c UdpConn) wait_for_write() !
|
|||||||
fn (c &UdpConn) str() string
|
fn (c &UdpConn) str() string
|
||||||
fn (mut c UdpConn) close() !
|
fn (mut c UdpConn) close() !
|
||||||
struct Unix {
|
struct Unix {
|
||||||
path [max_unix_path]char
|
path [max_unix_path]char
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# **WebDAV Server in V**
|
# **WebDAV Server in V**
|
||||||
|
|
||||||
This project implements a WebDAV server using the `vweb` framework and modules from `crystallib`. The server supports essential WebDAV file operations such as reading, writing, copying, moving, and deleting files and directories. It also includes **authentication** and **request logging** for better control and debugging.
|
This project implements a WebDAV server using the `veb` framework and modules from `crystallib`. The server supports essential WebDAV file operations such as reading, writing, copying, moving, and deleting files and directories. It also includes **authentication** and **request logging** for better control and debugging.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ sudo mount -t davfs <server_url> <mount_point>
|
|||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mount -t davfs http://localhost:8080 /mnt/webdav
|
sudo mount -t davfs http://localhost:8080 /mnt/webdav
|
||||||
```
|
```
|
||||||
@@ -82,6 +83,7 @@ Authorization: Basic <base64-encoded-credentials>
|
|||||||
|
|
||||||
**Example**:
|
**Example**:
|
||||||
For the credentials `admin:admin`, the header would look like this:
|
For the credentials `admin:admin`, the header would look like this:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
Authorization: Basic YWRtaW46YWRtaW4=
|
Authorization: Basic YWRtaW46YWRtaW4=
|
||||||
```
|
```
|
||||||
@@ -103,25 +105,32 @@ You can configure the WebDAV server using the following parameters when calling
|
|||||||
## **Example Workflow**
|
## **Example Workflow**
|
||||||
|
|
||||||
1. Start the server:
|
1. Start the server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
v run webdav_server.v
|
v run webdav_server.v
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Mount the server using `davfs`:
|
2. Mount the server using `davfs`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mount -t davfs http://localhost:8080 /mnt/webdav
|
sudo mount -t davfs http://localhost:8080 /mnt/webdav
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Perform operations:
|
3. Perform operations:
|
||||||
- Create a new file:
|
- Create a new file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "Hello WebDAV!" > /mnt/webdav/hello.txt
|
echo "Hello WebDAV!" > /mnt/webdav/hello.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
- List files:
|
- List files:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls /mnt/webdav
|
ls /mnt/webdav
|
||||||
```
|
```
|
||||||
|
|
||||||
- Delete a file:
|
- Delete a file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rm /mnt/webdav/hello.txt
|
rm /mnt/webdav/hello.txt
|
||||||
```
|
```
|
||||||
@@ -150,7 +159,6 @@ You can configure the WebDAV server using the following parameters when calling
|
|||||||
- Integration with persistent databases for user credentials.
|
- Integration with persistent databases for user credentials.
|
||||||
- TLS/SSL support for secure connections.
|
- TLS/SSL support for secure connections.
|
||||||
|
|
||||||
|
|
||||||
# WebDAV Property Model
|
# WebDAV Property Model
|
||||||
|
|
||||||
This file implements the WebDAV property model as defined in [RFC 4918](https://tools.ietf.org/html/rfc4918). It provides a set of property types that represent various WebDAV properties used in PROPFIND and PROPPATCH operations.
|
This file implements the WebDAV property model as defined in [RFC 4918](https://tools.ietf.org/html/rfc4918). It provides a set of property types that represent various WebDAV properties used in PROPFIND and PROPPATCH operations.
|
||||||
@@ -167,12 +175,13 @@ The `model_property.v` file defines:
|
|||||||
|
|
||||||
```v
|
```v
|
||||||
pub interface Property {
|
pub interface Property {
|
||||||
xml() string
|
xml() string
|
||||||
xml_name() string
|
xml_name() string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All WebDAV properties must implement:
|
All WebDAV properties must implement:
|
||||||
|
|
||||||
- `xml()`: Returns the full XML representation of the property with its value
|
- `xml()`: Returns the full XML representation of the property with its value
|
||||||
- `xml_name()`: Returns just the XML tag name of the property (used in property requests)
|
- `xml_name()`: Returns just the XML tag name of the property (used in property requests)
|
||||||
|
|
||||||
@@ -200,7 +209,6 @@ The file implements the following WebDAV property types:
|
|||||||
|
|
||||||
These property types are used when responding to WebDAV PROPFIND requests to describe resources in the WebDAV server.
|
These property types are used when responding to WebDAV PROPFIND requests to describe resources in the WebDAV server.
|
||||||
|
|
||||||
|
|
||||||
# WebDAV Locker
|
# WebDAV Locker
|
||||||
|
|
||||||
This file implements a locking mechanism for resources in a WebDAV context. It provides functionality to manage locks on resources, ensuring that they are not modified by multiple clients simultaneously.
|
This file implements a locking mechanism for resources in a WebDAV context. It provides functionality to manage locks on resources, ensuring that they are not modified by multiple clients simultaneously.
|
||||||
@@ -218,7 +226,7 @@ The `locker.v` file defines:
|
|||||||
```v
|
```v
|
||||||
struct Locker {
|
struct Locker {
|
||||||
mut:
|
mut:
|
||||||
locks map[string]Lock
|
locks map[string]Lock
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -229,8 +237,8 @@ mut:
|
|||||||
```v
|
```v
|
||||||
pub struct LockResult {
|
pub struct LockResult {
|
||||||
pub:
|
pub:
|
||||||
token string // The lock token
|
token string // The lock token
|
||||||
is_new_lock bool // Whether this is a new lock or an existing one
|
is_new_lock bool // Whether this is a new lock or an existing one
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import x.json2 as json
|
|||||||
// import freeflowuniverse.herolib.develop.gittools
|
// import freeflowuniverse.herolib.develop.gittools
|
||||||
import freeflowuniverse.herolib.core.pathlib
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
import freeflowuniverse.herolib.core.texttools
|
import freeflowuniverse.herolib.core.texttools
|
||||||
import vweb
|
import veb
|
||||||
import os
|
import os
|
||||||
|
|
||||||
pub struct Playground {
|
pub struct Playground {
|
||||||
vweb.Context
|
veb.Context
|
||||||
build pathlib.Path @[vweb_global]
|
veb.StaticHandler
|
||||||
|
build pathlib.Path @[veb_global]
|
||||||
}
|
}
|
||||||
|
|
||||||
@[params]
|
@[params]
|
||||||
@@ -50,11 +51,11 @@ pub fn new_playground(config PlaygroundConfig) !&Playground {
|
|||||||
build: build_dir
|
build: build_dir
|
||||||
}
|
}
|
||||||
pg.serve_examples(config.specs) or { return error('failed to serve examples:\n${err}') }
|
pg.serve_examples(config.specs) or { return error('failed to serve examples:\n${err}') }
|
||||||
pg.mount_static_folder_at('${build_dir.path}/static', '/static')
|
pg.mount_static_folder_at('${build_dir.path}/static', '/static')!
|
||||||
|
|
||||||
mut env_file := pathlib.get_file(path: '${build_dir.path}/env.js')!
|
mut env_file := pathlib.get_file(path: '${build_dir.path}/env.js')!
|
||||||
env_file.write(encode_env(config.specs)!)!
|
env_file.write(encode_env(config.specs)!)!
|
||||||
pg.serve_static('/env.js', env_file.path)
|
pg.serve_static('/env.js', env_file.path)!
|
||||||
return &pg
|
return &pg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,11 +87,11 @@ fn (mut pg Playground) serve_examples(specs_ []pathlib.Path) ! {
|
|||||||
return error('Failed to decode OpenRPC Spec ${spec}:\n${err}')
|
return error('Failed to decode OpenRPC Spec ${spec}:\n${err}')
|
||||||
}
|
}
|
||||||
name := texttools.name_fix(o.info.title)
|
name := texttools.name_fix(o.info.title)
|
||||||
pg.serve_static('/specs/${name}.json', spec.path)
|
pg.serve_static('/specs/${name}.json', spec.path)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut pg Playground) index() vweb.Result {
|
pub fn (mut pg Playground) index() veb.Result {
|
||||||
mut index := pathlib.get_file(path: '${pg.build.path}/index.html') or { panic(err) }
|
mut index := pathlib.get_file(path: '${pg.build.path}/index.html') or { panic(err) }
|
||||||
return pg.html(index.read() or { panic(err) })
|
return pg.html(index.read() or { panic(err) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import net.http
|
|||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
// session controller that be be added to vweb projects
|
// session controller that be be added to veb projects
|
||||||
pub struct EmailClient {
|
pub struct EmailClient {
|
||||||
url string @[required]
|
url string @[required]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module authentication
|
module authentication
|
||||||
|
|
||||||
import vweb
|
import veb
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import log
|
import log
|
||||||
@@ -8,13 +8,13 @@ import freeflowuniverse.herolib.ui.console
|
|||||||
|
|
||||||
const agent = 'Email Authentication Controller'
|
const agent = 'Email Authentication Controller'
|
||||||
|
|
||||||
// email authentication controller that be be added to vweb projects
|
// email authentication controller that be be added to veb projects
|
||||||
@[heap]
|
@[heap]
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
vweb.Context
|
veb.Context
|
||||||
callback string @[vweb_global]
|
callback string @[veb_global]
|
||||||
mut:
|
mut:
|
||||||
authenticator Authenticator @[vweb_global]
|
authenticator Authenticator @[veb_global]
|
||||||
}
|
}
|
||||||
|
|
||||||
@[params]
|
@[params]
|
||||||
@@ -32,7 +32,7 @@ pub fn new_controller(params ControllerParams) Controller {
|
|||||||
|
|
||||||
// route responsible for verifying email, email form should be posted here
|
// route responsible for verifying email, email form should be posted here
|
||||||
@[POST]
|
@[POST]
|
||||||
pub fn (mut app Controller) send_verification_mail() !vweb.Result {
|
pub fn (mut app Controller) send_verification_mail() !veb.Result {
|
||||||
config := json.decode(SendMailConfig, app.req.data)!
|
config := json.decode(SendMailConfig, app.req.data)!
|
||||||
app.authenticator.send_verification_mail(config) or { panic(err) }
|
app.authenticator.send_verification_mail(config) or { panic(err) }
|
||||||
return app.ok('')
|
return app.ok('')
|
||||||
@@ -40,7 +40,7 @@ pub fn (mut app Controller) send_verification_mail() !vweb.Result {
|
|||||||
|
|
||||||
// route responsible for verifying email, email form should be posted here
|
// route responsible for verifying email, email form should be posted here
|
||||||
@[POST]
|
@[POST]
|
||||||
pub fn (mut app Controller) is_verified() vweb.Result {
|
pub fn (mut app Controller) is_verified() veb.Result {
|
||||||
address := app.req.data
|
address := app.req.data
|
||||||
// checks if email verified every 2 seconds
|
// checks if email verified every 2 seconds
|
||||||
for {
|
for {
|
||||||
@@ -55,7 +55,7 @@ pub fn (mut app Controller) is_verified() vweb.Result {
|
|||||||
|
|
||||||
// route responsible for verifying email, email form should be posted here
|
// route responsible for verifying email, email form should be posted here
|
||||||
@[POST]
|
@[POST]
|
||||||
pub fn (mut app Controller) email_authentication() vweb.Result {
|
pub fn (mut app Controller) email_authentication() veb.Result {
|
||||||
config_ := json.decode(SendMailConfig, app.req.data) or {
|
config_ := json.decode(SendMailConfig, app.req.data) or {
|
||||||
app.set_status(422, 'Request payload does not follow anticipated formatting.')
|
app.set_status(422, 'Request payload does not follow anticipated formatting.')
|
||||||
return app.text('Request payload does not follow anticipated formatting.')
|
return app.text('Request payload does not follow anticipated formatting.')
|
||||||
@@ -84,7 +84,7 @@ pub fn (mut app Controller) email_authentication() vweb.Result {
|
|||||||
|
|
||||||
// route responsible for verifying email, email form should be posted here
|
// route responsible for verifying email, email form should be posted here
|
||||||
@[POST]
|
@[POST]
|
||||||
pub fn (mut app Controller) verify() vweb.Result {
|
pub fn (mut app Controller) verify() veb.Result {
|
||||||
config_ := json.decode(SendMailConfig, app.req.data) or {
|
config_ := json.decode(SendMailConfig, app.req.data) or {
|
||||||
app.set_status(422, 'Request payload does not follow anticipated formatting.')
|
app.set_status(422, 'Request payload does not follow anticipated formatting.')
|
||||||
return app.text('Request payload does not follow anticipated formatting.')
|
return app.text('Request payload does not follow anticipated formatting.')
|
||||||
@@ -126,7 +126,7 @@ pub:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@[POST]
|
@[POST]
|
||||||
pub fn (mut app Controller) authenticate() !vweb.Result {
|
pub fn (mut app Controller) authenticate() !veb.Result {
|
||||||
attempt := json.decode(AuthAttempt, app.req.data)!
|
attempt := json.decode(AuthAttempt, app.req.data)!
|
||||||
app.authenticator.authenticate(attempt.address, attempt.cypher) or {
|
app.authenticator.authenticate(attempt.address, attempt.cypher) or {
|
||||||
app.set_status(401, err.msg())
|
app.set_status(401, err.msg())
|
||||||
@@ -136,7 +136,7 @@ pub fn (mut app Controller) authenticate() !vweb.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@['/authentication_link/:address/:cypher']
|
@['/authentication_link/:address/:cypher']
|
||||||
pub fn (mut app Controller) authentication_link(address string, cypher string) !vweb.Result {
|
pub fn (mut app Controller) authentication_link(address string, cypher string) !veb.Result {
|
||||||
app.authenticator.authenticate(address, cypher) or {
|
app.authenticator.authenticate(address, cypher) or {
|
||||||
app.set_status(401, err.msg())
|
app.set_status(401, err.msg())
|
||||||
return app.text('Failed to authenticate')
|
return app.text('Failed to authenticate')
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import crypto.rand
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
// JWT code in this page is from
|
// JWT code in this page is from
|
||||||
// https://github.com/vlang/v/blob/master/examples/vweb_orm_jwt/src/auth_services.v
|
// https://github.com/vlang/v/blob/master/examples/veb_orm_jwt/src/auth_services.v
|
||||||
// credit to https://github.com/enghitalo
|
// credit to https://github.com/enghitalo
|
||||||
|
|
||||||
pub struct JsonWebToken {
|
pub struct JsonWebToken {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module @{name}
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import cli { Command }
|
import cli { Command }
|
||||||
import vweb
|
import veb
|
||||||
import freeflowuniverse.herolib.schemas.openrpc
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
import freeflowuniverse.herolib.core.pathlib
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ fn playground(cmd Command) ! {
|
|||||||
dest: pathlib.get_dir(path: playground_path)!
|
dest: pathlib.get_dir(path: playground_path)!
|
||||||
specs: [pathlib.get_file(path:openrpc_path)!]
|
specs: [pathlib.get_file(path:openrpc_path)!]
|
||||||
)!
|
)!
|
||||||
vweb.run(pg, 8080)
|
veb.run(pg, 8080)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env -S v -n -cg -w -enable-globals run
|
#!/usr/bin/env -S v -n -cg -w -enable-globals run
|
||||||
|
|
||||||
import freeflowuniverse.herolib.baobab.stages.accountant
|
import freeflowuniverse.herolib.baobab.stages.accountant
|
||||||
import vweb
|
import veb
|
||||||
import freeflowuniverse.herolib.schemas.openrpc
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
import os
|
import os
|
||||||
import freeflowuniverse.herolib.core.pathlib
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
@@ -13,4 +13,4 @@ pg := openrpc.new_playground(
|
|||||||
dest: pathlib.get_dir(path: playground_path)!
|
dest: pathlib.get_dir(path: playground_path)!
|
||||||
specs: [pathlib.get_file(path:openrpc_path)!]
|
specs: [pathlib.get_file(path:openrpc_path)!]
|
||||||
)!
|
)!
|
||||||
vweb.run(pg, 8080)
|
veb.run(pg, 8080)
|
||||||
Reference in New Issue
Block a user