From a8bded8d896a51bb48aaedf3bfbc80e00189ba23 Mon Sep 17 00:00:00 2001 From: Brad Date: Mon, 15 Dec 2025 05:14:16 -0500 Subject: [PATCH] veb: add an early startup panic error message, when the result type of route handler methods *is not* `veb.Result` (fix #25970) (#25973) --- vlib/veb/parse.v | 20 +++++++++++++++++ vlib/veb/tests/invalid_return_type_test.v | 26 +++++++++++++++++++++++ vlib/veb/veb.v | 5 +++++ 3 files changed, 51 insertions(+) create mode 100644 vlib/veb/tests/invalid_return_type_test.v diff --git a/vlib/veb/parse.v b/vlib/veb/parse.v index b1f0f3990..132bbe167 100644 --- a/vlib/veb/parse.v +++ b/vlib/veb/parse.v @@ -95,3 +95,23 @@ fn parse_form_from_request(request http.Request) !(map[string]string, map[string } return http.parse_form(request.data), map[string][]http.FileData{} } + +// has_route_attributes checks if a method has attributes that indicate it should be a route handler +fn has_route_attributes(attrs []string) bool { + if attrs.len == 0 { + return false + } + for attr in attrs { + attru := attr.to_upper() + if attru in ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] { + return true + } + if attr.starts_with('/') { + return true + } + if attr.starts_with('host:') { + return true + } + } + return false +} diff --git a/vlib/veb/tests/invalid_return_type_test.v b/vlib/veb/tests/invalid_return_type_test.v new file mode 100644 index 000000000..e9ec6e7bd --- /dev/null +++ b/vlib/veb/tests/invalid_return_type_test.v @@ -0,0 +1,26 @@ +import veb + +pub struct App {} + +struct Context { + veb.Context +} + +// Test that methods with route attributes but wrong return type are caught +fn test_invalid_return_type_is_detected() { + mut app := &App{} + + // This should fail because get_task has route attributes but returns !veb.Result + veb.generate_routes[App, Context](app) or { + assert err.msg().contains('invalid return type'), 'Expected error about invalid return type, got: ${err.msg()}' + assert err.msg().contains('get_task'), 'Expected error to mention method name, got: ${err.msg()}' + return + } + + assert false, 'Expected generate_routes to return an error for invalid return type' +} + +@['/test'; get] +pub fn (app &App) get_task(mut ctx Context) !veb.Result { + return ctx.text('Hello') +} diff --git a/vlib/veb/veb.v b/vlib/veb/veb.v index 5f1a0ba79..78ea70017 100644 --- a/vlib/veb/veb.v +++ b/vlib/veb/veb.v @@ -53,6 +53,11 @@ fn generate_routes[A, X](app &A) !map[string]Route { } routes[method.name] = route + } $else { + // If we have route attributes, but the wrong return type, return an error + if has_route_attributes(method.attrs) { + return error('method `${method.name}` has route attributes but invalid return type. Handler methods must return `veb.Result`, not `!veb.Result` or other types') + } } } return routes -- 2.39.5