module main import vweb import time import os struct App { vweb.Context timeout int global_config shared Config middlewares map[string][]vweb.Middleware } struct Config { pub mut: middleware_text string } fn exit_after_timeout(timeout_in_ms int) { time.sleep(timeout_in_ms * time.millisecond) println('>> webserver: pid: ${os.getpid()}, exiting ...') exit(0) } fn main() { if os.args.len != 3 { panic('Usage: `vweb_test_server.exe PORT TIMEOUT_IN_MILLISECONDS`') } http_port := os.args[1].int() assert http_port > 0 timeout := os.args[2].int() spawn exit_after_timeout(timeout) shared config := &Config{} app := &App{ timeout: timeout global_config: config middlewares: { '/single': [middleware1] '/single_post': [middleware1] '/multiple': [middleware1, middleware2] '/multiple_post': [middleware1, middleware2] '/combined': [middleware1, middleware2] '/combined_post': [middleware1, middleware2] '/admin/': [middleware1] '/other/': [middleware1, middleware2] '/redirect': [middleware_redirect] } } eprintln('>> webserver: pid: ${os.getpid()}, started on http://localhost:${http_port}/ , with maximum runtime of ${app.timeout} milliseconds.') vweb.run_at(app, host: 'localhost', port: http_port, family: .ip)! } // normal routes: [middleware: app_middleware] ['/'] pub fn (mut app App) index() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}index') } ['/single'] pub fn (mut app App) single() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}single') } ['/multiple'] pub fn (mut app App) multiple() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}multiple') } [middleware: app_middleware] ['/combined'] pub fn (mut app App) combined() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}combined') } ['/admin/nested'] pub fn (mut app App) nested() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}nested') } // above routes + post [middleware: app_middleware] ['/index_post'; post] pub fn (mut app App) index_post() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}index_post:${app.req.data}') } ['/single_post'; post] pub fn (mut app App) single_post() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}single_post:${app.req.data}') } ['/multiple_post'; post] pub fn (mut app App) multiple_post() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}multiple_post:${app.req.data}') } [middleware: app_middleware] ['/combined_post'; post] pub fn (mut app App) combined_post() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}combined_post:${app.req.data}') } ['/admin/nested_post'; post] pub fn (mut app App) nested_post() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}nested_post:${app.req.data}') } // dynamic routes ['/admin/:dynamic'] pub fn (mut app App) admin_dynamic(dynamic string) vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}admin_dynamic:${dynamic}') } [middleware: app_middleware] ['/other/:dynamic'] pub fn (mut app App) combined_dynamic(dynamic string) vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}combined_dynamic:${dynamic}') } // redirect routes: [middleware: app_redirect] ['/app_redirect'] pub fn (mut app App) app_redirect_route() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}should_never_reach!') } ['/redirect'] pub fn (mut app App) redirect_route() vweb.Result { mut result := '' rlock app.global_config { result = app.global_config.middleware_text } return app.text('${result}should_never_reach!') } // middleware functions: pub fn (mut app App) before_request() { lock app.global_config { app.global_config.middleware_text = '0' } } pub fn (mut app App) app_middleware() bool { lock app.global_config { app.global_config.middleware_text += 'app_middleware' } return true } pub fn (mut app App) app_redirect() bool { app.redirect('/') return false } fn middleware1(mut ctx vweb.Context) bool { ctx.conn.write_string('m1') or { panic(err) } return true } fn middleware2(mut ctx vweb.Context) bool { ctx.conn.write_string('m2') or { panic(err) } return true } fn middleware_redirect(mut ctx vweb.Context) bool { ctx.conn.write_string('m_redirect') or { panic(err) } ctx.redirect('/') return false } // utility functions: pub fn (mut app App) shutdown() vweb.Result { session_key := app.get_cookie('skey') or { return app.not_found() } if session_key != 'superman' { return app.not_found() } spawn app.gracefull_exit() return app.ok('good bye') } fn (mut app App) gracefull_exit() { eprintln('>> webserver: gracefull_exit') time.sleep(100 * time.millisecond) exit(0) }