mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so v doc -v -unsafe-run-examples -f none vlib/
could be added to the CI
This commit is contained in:
parent
c83cc174a4
commit
bd408289d5
9 changed files with 46 additions and 42 deletions
|
@ -62,7 +62,11 @@ fn (mut vd VDoc) run_examples(dn doc.DocNode) {
|
||||||
vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v')
|
vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v')
|
||||||
// eprintln('>>> example dn.file_path: ${dn.file_path} | mod_name: ${mod_name} | vsource_path: ${vsource_path} | code: `${code}`')
|
// eprintln('>>> example dn.file_path: ${dn.file_path} | mod_name: ${mod_name} | vsource_path: ${vsource_path} | code: `${code}`')
|
||||||
import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' }
|
import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' }
|
||||||
source := '${import_clause}fn main() {\n\t${code}\n}\n'
|
source := if import_clause != '' && !code.contains('import ') {
|
||||||
|
'${import_clause}fn main() {\n\t${code}\n}\n'
|
||||||
|
} else {
|
||||||
|
code
|
||||||
|
}
|
||||||
os.write_file(vsource_path, source) or { continue }
|
os.write_file(vsource_path, source) or { continue }
|
||||||
vd.vprintln('>>> vd.example_oks: ${vd.example_oks:5} | vd.example_failures: ${vd.example_failures:5} | examples.len: ${examples.len} | source.len: ${source.len:5} | dn.name: ${dn.name}')
|
vd.vprintln('>>> vd.example_oks: ${vd.example_oks:5} | vd.example_failures: ${vd.example_failures:5} | examples.len: ${examples.len} | source.len: ${source.len:5} | dn.name: ${dn.name}')
|
||||||
cmd := '${os.quoted_path(vexe)} ${voptions} ${os.quoted_path(vsource_path)}'
|
cmd := '${os.quoted_path(vexe)} ${voptions} ${os.quoted_path(vsource_path)}'
|
||||||
|
|
|
@ -206,7 +206,7 @@ pub fn (am AssetManager) exists(asset_type AssetType, include_name string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// include css/js files in your veb app from templates
|
// include css/js files in your veb app from templates
|
||||||
// Example:
|
// Usage example:
|
||||||
// ```html
|
// ```html
|
||||||
// @{app.am.include(.css, 'main.css')}
|
// @{app.am.include(.css, 'main.css')}
|
||||||
// ```
|
// ```
|
||||||
|
|
|
@ -120,7 +120,7 @@ fn validate_middleware[T](mut ctx T, raw_handlers []voidptr) bool {
|
||||||
// encode_gzip adds gzip encoding to the HTTP Response body.
|
// encode_gzip adds gzip encoding to the HTTP Response body.
|
||||||
// This middleware does not encode files, if you return `ctx.file()`.
|
// This middleware does not encode files, if you return `ctx.file()`.
|
||||||
// Register this middleware as last!
|
// Register this middleware as last!
|
||||||
// Example: app.use(veb.encode_gzip[Context]())
|
// Usage example: app.use(veb.encode_gzip[Context]())
|
||||||
pub fn encode_gzip[T]() MiddlewareOptions[T] {
|
pub fn encode_gzip[T]() MiddlewareOptions[T] {
|
||||||
return MiddlewareOptions[T]{
|
return MiddlewareOptions[T]{
|
||||||
after: true
|
after: true
|
||||||
|
@ -155,7 +155,7 @@ pub fn encode_gzip[T]() MiddlewareOptions[T] {
|
||||||
|
|
||||||
// decode_gzip decodes the body of a gzip'ed HTTP request.
|
// decode_gzip decodes the body of a gzip'ed HTTP request.
|
||||||
// Register this middleware before you do anything with the request body!
|
// Register this middleware before you do anything with the request body!
|
||||||
// Example: app.use(veb.decode_gzip[Context]())
|
// Usage example: app.use(veb.decode_gzip[Context]())
|
||||||
pub fn decode_gzip[T]() MiddlewareOptions[T] {
|
pub fn decode_gzip[T]() MiddlewareOptions[T] {
|
||||||
return MiddlewareOptions[T]{
|
return MiddlewareOptions[T]{
|
||||||
handler: fn [T](mut ctx T) bool {
|
handler: fn [T](mut ctx T) bool {
|
||||||
|
@ -299,7 +299,7 @@ pub fn (options &CorsOptions) validate_request(mut ctx Context) bool {
|
||||||
|
|
||||||
// cors handles cross-origin requests by adding Access-Control-* headers to a
|
// cors handles cross-origin requests by adding Access-Control-* headers to a
|
||||||
// preflight request and validating the headers of a cross-origin request.
|
// preflight request and validating the headers of a cross-origin request.
|
||||||
// Example:
|
// Usage example:
|
||||||
// ```v
|
// ```v
|
||||||
// app.use(veb.cors[Context](veb.CorsOptions{
|
// app.use(veb.cors[Context](veb.CorsOptions{
|
||||||
// origins: ['*']
|
// origins: ['*']
|
||||||
|
|
|
@ -142,7 +142,7 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
// run_at - start a new veb server, listening only on a specific address `host`, at the specified `port`
|
// run_at - start a new veb server, listening only on a specific address `host`, at the specified `port`
|
||||||
// Example: veb.run_at(new_app(), veb.RunParams{ host: 'localhost' port: 8099 family: .ip }) or { panic(err) }
|
// Usage example: veb.run_at(new_app(), host: 'localhost' port: 8099 family: .ip)!
|
||||||
@[direct_array_access; manualfree]
|
@[direct_array_access; manualfree]
|
||||||
pub fn run_at[A, X](mut global_app A, params RunParams) ! {
|
pub fn run_at[A, X](mut global_app A, params RunParams) ! {
|
||||||
if params.port <= 0 || params.port > 65535 {
|
if params.port <= 0 || params.port > 65535 {
|
||||||
|
|
|
@ -200,8 +200,8 @@ struct Route {
|
||||||
host string
|
host string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defining this method is optional.
|
// init_server is called at the server start.
|
||||||
// This method called at server start.
|
// Note: defining this method is optional.
|
||||||
// You can use it for initializing globals.
|
// You can use it for initializing globals.
|
||||||
pub fn (ctx &Context) init_server() {
|
pub fn (ctx &Context) init_server() {
|
||||||
eprintln('init_server() has been deprecated, please init your web app in `fn main()`')
|
eprintln('init_server() has been deprecated, please init your web app in `fn main()`')
|
||||||
|
@ -223,7 +223,7 @@ pub fn (ctx &Context) before_accept_loop() {
|
||||||
pub fn (ctx &Context) before_request() {}
|
pub fn (ctx &Context) before_request() {}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
// vweb intern function
|
// send_response_to_client sends back a custom response to the client, with the given `mimetype` and content in `res`.
|
||||||
@[manualfree]
|
@[manualfree]
|
||||||
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 {
|
||||||
|
@ -253,26 +253,26 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response with payload and content-type `text/html`
|
// html responds with payload and content-type `text/html`
|
||||||
pub fn (mut ctx Context) html(payload string) Result {
|
pub fn (mut ctx Context) html(payload string) Result {
|
||||||
ctx.send_response_to_client('text/html', payload)
|
ctx.send_response_to_client('text/html', payload)
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response with s as payload and content-type `text/plain`
|
// text responds with s as payload and 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 with json_s as payload and content-type `application/json`
|
// json responds with json_s as payload and content-type `application/json`
|
||||||
pub fn (mut ctx Context) json[T](j T) Result {
|
pub fn (mut ctx Context) json[T](j T) Result {
|
||||||
json_s := json.encode(j)
|
json_s := json.encode(j)
|
||||||
ctx.send_response_to_client('application/json', json_s)
|
ctx.send_response_to_client('application/json', json_s)
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response with a pretty-printed JSON result
|
// json_pretty responds with a pretty-printed JSON result
|
||||||
pub fn (mut ctx Context) json_pretty[T](j T) Result {
|
pub fn (mut ctx Context) json_pretty[T](j T) Result {
|
||||||
json_s := json.encode_pretty(j)
|
json_s := json.encode_pretty(j)
|
||||||
ctx.send_response_to_client('application/json', json_s)
|
ctx.send_response_to_client('application/json', json_s)
|
||||||
|
@ -280,7 +280,7 @@ pub fn (mut ctx Context) json_pretty[T](j T) Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
// Response with file as payload
|
// file responds with the content of the given file as payload.
|
||||||
pub fn (mut ctx Context) file(f_path string) Result {
|
pub fn (mut ctx Context) file(f_path string) Result {
|
||||||
if !os.exists(f_path) {
|
if !os.exists(f_path) {
|
||||||
eprintln('[vweb] file ${f_path} does not exist')
|
eprintln('[vweb] file ${f_path} does not exist')
|
||||||
|
@ -302,7 +302,7 @@ pub fn (mut ctx Context) file(f_path string) Result {
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response with s as payload and sets the status code to HTTP_OK
|
// ok responds with s as payload and sets the status code to HTTP_OK
|
||||||
pub fn (mut ctx Context) ok(s string) Result {
|
pub fn (mut ctx Context) ok(s string) Result {
|
||||||
ctx.set_status(200, 'OK')
|
ctx.set_status(200, 'OK')
|
||||||
ctx.send_response_to_client(ctx.content_type, s)
|
ctx.send_response_to_client(ctx.content_type, s)
|
||||||
|
@ -310,7 +310,7 @@ pub fn (mut ctx Context) ok(s string) Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
// Response a server error
|
// server_error will send back an error response to the client.
|
||||||
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}')
|
||||||
|
@ -322,13 +322,14 @@ pub fn (mut ctx Context) server_error(ecode int) Result {
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RedirectParams represent the optional parameters to redirect/2 .
|
||||||
@[params]
|
@[params]
|
||||||
pub struct RedirectParams {
|
pub struct RedirectParams {
|
||||||
pub:
|
pub:
|
||||||
status_code int = 302
|
status_code int = 302
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to an url
|
// redirect to an url.
|
||||||
pub fn (mut ctx Context) redirect(url string, params RedirectParams) Result {
|
pub fn (mut ctx Context) redirect(url string, params RedirectParams) Result {
|
||||||
if ctx.done {
|
if ctx.done {
|
||||||
return Result{}
|
return Result{}
|
||||||
|
@ -344,7 +345,7 @@ pub fn (mut ctx Context) redirect(url string, params RedirectParams) Result {
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send an not_found response
|
// not_found send an not_found response.
|
||||||
pub fn (mut ctx Context) not_found() Result {
|
pub fn (mut ctx Context) not_found() Result {
|
||||||
// TODO: add a [must_be_returned] attribute, so that the caller is forced to use `return app.not_found()`
|
// TODO: add a [must_be_returned] attribute, so that the caller is forced to use `return app.not_found()`
|
||||||
if ctx.done {
|
if ctx.done {
|
||||||
|
@ -356,7 +357,7 @@ pub fn (mut ctx Context) not_found() Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
// Sets a cookie
|
// set_cookie sets a cookie.
|
||||||
pub fn (mut ctx Context) set_cookie(cookie http.Cookie) {
|
pub fn (mut ctx Context) set_cookie(cookie http.Cookie) {
|
||||||
cookie_raw := cookie.str()
|
cookie_raw := cookie.str()
|
||||||
if cookie_raw == '' {
|
if cookie_raw == '' {
|
||||||
|
@ -366,13 +367,13 @@ pub fn (mut ctx Context) set_cookie(cookie http.Cookie) {
|
||||||
ctx.add_header('Set-Cookie', cookie_raw)
|
ctx.add_header('Set-Cookie', cookie_raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the response content type
|
// set_content_type 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
// Sets a cookie with a `expire_date`
|
// set_cookie_with_expire_date sets a cookie with an `expire_date`.
|
||||||
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) {
|
||||||
cookie := http.Cookie{
|
cookie := http.Cookie{
|
||||||
name: key
|
name: key
|
||||||
|
@ -382,7 +383,7 @@ pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, exp
|
||||||
ctx.set_cookie(cookie)
|
ctx.set_cookie(cookie)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a cookie by a key
|
// get_cookie get the value of a cookie, given its key.
|
||||||
pub fn (ctx &Context) get_cookie(key string) !string {
|
pub fn (ctx &Context) get_cookie(key string) !string {
|
||||||
c := ctx.req.cookie(key) or { return error('Cookie not found') }
|
c := ctx.req.cookie(key) or { return error('Cookie not found') }
|
||||||
return c.value
|
return c.value
|
||||||
|
@ -413,12 +414,12 @@ pub fn (ctx &Context) get_header(key string) string {
|
||||||
return ctx.req.header.get_custom(key) or { '' }
|
return ctx.req.header.get_custom(key) or { '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_value sets a value on the context
|
// set_value sets a value on the context.
|
||||||
pub fn (mut ctx Context) set_value(key context.Key, value context.Any) {
|
pub fn (mut ctx Context) set_value(key context.Key, value context.Any) {
|
||||||
ctx.ctx = context.with_value(ctx.ctx, key, value)
|
ctx.ctx = context.with_value(ctx.ctx, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_value gets a value from the context
|
// get_value gets a value from the context.
|
||||||
pub fn (ctx &Context) get_value[T](key context.Key) ?T {
|
pub fn (ctx &Context) get_value[T](key context.Key) ?T {
|
||||||
if val := ctx.ctx.value(key) {
|
if val := ctx.ctx.value(key) {
|
||||||
match val {
|
match val {
|
||||||
|
@ -495,7 +496,7 @@ pub mut:
|
||||||
controllers []&ControllerPath
|
controllers []&ControllerPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// controller generates a new Controller for the main app
|
// controller generates a new Controller for the main app.
|
||||||
pub fn controller[T](path string, global_app &T) &ControllerPath {
|
pub fn controller[T](path string, global_app &T) &ControllerPath {
|
||||||
routes := generate_routes(global_app) or { panic(err.msg()) }
|
routes := generate_routes(global_app) or { panic(err.msg()) }
|
||||||
|
|
||||||
|
@ -513,14 +514,14 @@ pub fn controller[T](path string, global_app &T) &ControllerPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// controller_host generates a controller which only handles incoming requests from the `host` domain
|
// controller_host generates a controller which only handles incoming requests from the `host` domain.
|
||||||
pub fn controller_host[T](host string, path string, global_app &T) &ControllerPath {
|
pub fn controller_host[T](host string, path string, global_app &T) &ControllerPath {
|
||||||
mut ctrl := controller(path, global_app)
|
mut ctrl := controller(path, global_app)
|
||||||
ctrl.host = host
|
ctrl.host = host
|
||||||
return ctrl
|
return ctrl
|
||||||
}
|
}
|
||||||
|
|
||||||
// run - start a new VWeb server, listening to all available addresses, at the specified `port`
|
// run - start a new VWeb server, listening to all available addresses, at the specified `port`.
|
||||||
pub fn run[T](global_app &T, port int) {
|
pub fn run[T](global_app &T, port int) {
|
||||||
run_at[T](global_app, host: '', port: port, family: .ip6) or { panic(err.msg()) }
|
run_at[T](global_app, host: '', port: port, family: .ip6) or { panic(err.msg()) }
|
||||||
}
|
}
|
||||||
|
@ -537,8 +538,8 @@ pub:
|
||||||
startup_message string
|
startup_message string
|
||||||
}
|
}
|
||||||
|
|
||||||
// run_at - start a new VWeb server, listening only on a specific address `host`, at the specified `port`
|
// run_at - start a new VWeb server, listening only on a specific address `host`, at the specified `port`.
|
||||||
// Example: vweb.run_at(new_app(), vweb.RunParams{ host: 'localhost' port: 8099 family: .ip }) or { panic(err) }
|
// Usage example: vweb.run_at(new_app(), host: 'localhost' port: 8099 family: .ip)!
|
||||||
@[manualfree]
|
@[manualfree]
|
||||||
pub fn run_at[T](global_app &T, params RunParams) ! {
|
pub fn run_at[T](global_app &T, params RunParams) ! {
|
||||||
if params.port <= 0 || params.port > 65535 {
|
if params.port <= 0 || params.port > 65535 {
|
||||||
|
|
|
@ -13,10 +13,10 @@ pub struct PrivateKey {
|
||||||
// See `enum Kind` for all of availables choice's type (kind) of key.
|
// See `enum Kind` for all of availables choice's type (kind) of key.
|
||||||
// Its also support to generate keys based on the seed or private bytes through
|
// Its also support to generate keys based on the seed or private bytes through
|
||||||
// provided options. See available options in `KeyOpts`.
|
// provided options. See available options in `KeyOpts`.
|
||||||
// Example:
|
// Usage example:
|
||||||
// ```
|
// ```v
|
||||||
// PrivateKey.new()!
|
// pk1 := slhdsa.PrivateKey.new()!; println(pk1)
|
||||||
// PrivateKey.new(kind: .sha2_128s)
|
// pk2 := slhdsa.PrivateKey.new(kind: .sha2_128s)!; println(pk2)
|
||||||
// ```
|
// ```
|
||||||
pub fn PrivateKey.new(opt KeyOpts) !PrivateKey {
|
pub fn PrivateKey.new(opt KeyOpts) !PrivateKey {
|
||||||
match opt.flag {
|
match opt.flag {
|
||||||
|
|
|
@ -63,7 +63,8 @@ pub fn (bs BitString) payload() ![]u8 {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (bs BitString) str() string {
|
// str returns a string representation of the current state of bs.
|
||||||
|
pub fn (bs BitString) str() string {
|
||||||
return 'BitString: ${bs.data.hex()} (${bs.pad})'
|
return 'BitString: ${bs.data.hex()} (${bs.pad})'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +117,8 @@ fn BitString.decode_with_rule(bytes []u8, rule EncodingRule) !(BitString, int) {
|
||||||
// Example:
|
// Example:
|
||||||
// ```v
|
// ```v
|
||||||
// import x.encoding.asn1
|
// import x.encoding.asn1
|
||||||
//
|
|
||||||
// bs := asn1.BitString.from_binary_string('011010001')!
|
// bs := asn1.BitString.from_binary_string('011010001')!
|
||||||
// assert (bs.pad == 7 && bs.data == [u8(0x68), 0x80]) == true
|
// assert bs.str() == 'BitString: 6880 (7)'
|
||||||
// ```
|
// ```
|
||||||
pub fn BitString.from_binary_string(s string) !BitString {
|
pub fn BitString.from_binary_string(s string) !BitString {
|
||||||
res, pad := parse_bits_string(s)!
|
res, pad := parse_bits_string(s)!
|
||||||
|
|
|
@ -38,9 +38,9 @@ pub fn verify_session_id(raw_sid string, secret []u8) (string, bool) {
|
||||||
|
|
||||||
// CurrentSession contains the session data during a request.
|
// CurrentSession contains the session data during a request.
|
||||||
// If you use x.vweb you could embed it on your Context struct to have easy access to the session id and data.
|
// If you use x.vweb you could embed it on your Context struct to have easy access to the session id and data.
|
||||||
// Example:
|
// Usage example:
|
||||||
// ```v
|
// ```v
|
||||||
// pub struct Context {
|
// struct Context {
|
||||||
// vweb.Context
|
// vweb.Context
|
||||||
// sessions.CurrentSessions[User]
|
// sessions.CurrentSessions[User]
|
||||||
// }
|
// }
|
||||||
|
@ -65,7 +65,7 @@ pub:
|
||||||
// Sessions can be used to easily integrate sessions with x.vweb.
|
// Sessions can be used to easily integrate sessions with x.vweb.
|
||||||
// This struct contains the store that holds all session data it also provides
|
// This struct contains the store that holds all session data it also provides
|
||||||
// an easy way to manage sessions in your vweb app.
|
// an easy way to manage sessions in your vweb app.
|
||||||
// Example:
|
// Usage example:
|
||||||
// ```v
|
// ```v
|
||||||
// pub struct App {
|
// pub struct App {
|
||||||
// pub mut:
|
// pub mut:
|
||||||
|
|
|
@ -6,8 +6,7 @@ import veb
|
||||||
// middleware can be used to add session middleware to your vweb app to ensure
|
// middleware can be used to add session middleware to your vweb app to ensure
|
||||||
// a valid session always exists. If a valid session exists the session data will
|
// a valid session always exists. If a valid session exists the session data will
|
||||||
// be loaded into `session_data`, else a new session id will be generated.
|
// be loaded into `session_data`, else a new session id will be generated.
|
||||||
// You have to pass the Context type as the generic type
|
// You have to pass the Context type as the generic type.
|
||||||
// Example: app.use(app.sessions.middleware[Context]())
|
|
||||||
pub fn create[T, X](mut s sessions.Sessions[T]) veb.MiddlewareOptions[X] {
|
pub fn create[T, X](mut s sessions.Sessions[T]) veb.MiddlewareOptions[X] {
|
||||||
return veb.MiddlewareOptions[X]{
|
return veb.MiddlewareOptions[X]{
|
||||||
handler: fn [mut s] [T, X](mut ctx X) bool {
|
handler: fn [mut s] [T, X](mut ctx X) bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue