| 1 | module veb |
| 2 | |
| 3 | import net.http |
| 4 | import net.urllib |
| 5 | |
| 6 | const issue_20757_allowed_origin = 'https://vlang.io' |
| 7 | const issue_20757_route = '/before_request' |
| 8 | const issue_20757_secret_key = 'secretkey' |
| 9 | |
| 10 | struct Issue20757Context { |
| 11 | Context |
| 12 | } |
| 13 | |
| 14 | fn (mut ctx Issue20757Context) before_request() { |
| 15 | if ctx.req.url != issue_20757_route { |
| 16 | return |
| 17 | } |
| 18 | ctx.set_custom_header('X-BEFORE-REQUEST', 'true') or {} |
| 19 | key := ctx.get_header(.authorization) or { 'Basic none' } |
| 20 | if key != 'Basic ${issue_20757_secret_key}' { |
| 21 | ctx.request_error('Authorization failed') |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | struct Issue20757App { |
| 26 | Middleware[Issue20757Context] |
| 27 | } |
| 28 | |
| 29 | @['/before_request'] |
| 30 | fn (app &Issue20757App) authorized(mut ctx Issue20757Context) Result { |
| 31 | return ctx.text('authorized') |
| 32 | } |
| 33 | |
| 34 | fn new_issue_20757_context(auth_header string) Issue20757Context { |
| 35 | mut header := http.new_header_from_map({ |
| 36 | http.CommonHeader.origin: issue_20757_allowed_origin |
| 37 | }) |
| 38 | if auth_header != '' { |
| 39 | header.add(.authorization, auth_header) |
| 40 | } |
| 41 | return Issue20757Context{ |
| 42 | Context: Context{ |
| 43 | req: http.Request{ |
| 44 | method: .get |
| 45 | url: issue_20757_route |
| 46 | header: header |
| 47 | } |
| 48 | query: {} |
| 49 | form: {} |
| 50 | files: {} |
| 51 | res: http.Response{ |
| 52 | header: http.new_header() |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | fn new_issue_20757_app() &Issue20757App { |
| 59 | mut app := &Issue20757App{} |
| 60 | app.use(cors[Issue20757Context](CorsOptions{ |
| 61 | origins: [issue_20757_allowed_origin] |
| 62 | allowed_methods: [.get] |
| 63 | })) |
| 64 | return app |
| 65 | } |
| 66 | |
| 67 | fn test_before_request_still_runs_with_cors_middleware() { |
| 68 | mut app := new_issue_20757_app() |
| 69 | mut ctx := new_issue_20757_context('') |
| 70 | routes := generate_routes[Issue20757App, Issue20757Context](app)! |
| 71 | url := urllib.parse(issue_20757_route)! |
| 72 | |
| 73 | handle_route[Issue20757App, Issue20757Context](mut app, mut ctx, url, '', &routes) |
| 74 | |
| 75 | assert ctx.res.status_code == int(http.Status.bad_request) |
| 76 | assert ctx.res.body == 'Authorization failed' |
| 77 | assert ctx.res.header.get_custom('X-BEFORE-REQUEST')! == 'true' |
| 78 | } |
| 79 | |
| 80 | fn test_before_request_can_allow_cors_request() { |
| 81 | mut app := new_issue_20757_app() |
| 82 | mut ctx := new_issue_20757_context('Basic ${issue_20757_secret_key}') |
| 83 | routes := generate_routes[Issue20757App, Issue20757Context](app)! |
| 84 | url := urllib.parse(issue_20757_route)! |
| 85 | |
| 86 | handle_route[Issue20757App, Issue20757Context](mut app, mut ctx, url, '', &routes) |
| 87 | |
| 88 | assert ctx.res.status_code == int(http.Status.ok) |
| 89 | assert ctx.res.body == 'authorized' |
| 90 | assert ctx.res.header.get_custom('X-BEFORE-REQUEST')! == 'true' |
| 91 | assert ctx.res.header.get(.access_control_allow_origin)! == issue_20757_allowed_origin |
| 92 | } |
| 93 | |