| 1 | // vtest build: !windows // fasthttp.Server.run is not implemented on windows yet |
| 2 | import veb |
| 3 | import net.http |
| 4 | import os |
| 5 | import time |
| 6 | |
| 7 | const port = 13012 |
| 8 | const localserver = 'http://127.0.0.1:${port}' |
| 9 | const exit_after = time.second * 10 |
| 10 | const allowed_origin = 'https://vlang.io' |
| 11 | const cors_options = veb.CorsOptions{ |
| 12 | origins: [allowed_origin] |
| 13 | allowed_methods: [.get, .head] |
| 14 | } |
| 15 | |
| 16 | pub struct Context { |
| 17 | veb.Context |
| 18 | } |
| 19 | |
| 20 | pub struct App { |
| 21 | veb.Middleware[Context] |
| 22 | mut: |
| 23 | started chan bool |
| 24 | } |
| 25 | |
| 26 | pub fn (mut app App) before_accept_loop() { |
| 27 | app.started <- true |
| 28 | } |
| 29 | |
| 30 | pub fn (app &App) index(mut context Context) veb.Result { |
| 31 | return context.text('index') |
| 32 | } |
| 33 | |
| 34 | @[post] |
| 35 | pub fn (app &App) post(mut context Context) veb.Result { |
| 36 | return context.text('post') |
| 37 | } |
| 38 | |
| 39 | fn testsuite_begin() { |
| 40 | os.chdir(os.dir(@FILE))! |
| 41 | spawn fn () { |
| 42 | time.sleep(exit_after) |
| 43 | assert true == false, 'timeout reached!' |
| 44 | exit(1) |
| 45 | }() |
| 46 | |
| 47 | mut app := &App{} |
| 48 | app.use(veb.cors[Context](cors_options)) |
| 49 | |
| 50 | spawn veb.run_at[App, Context](mut app, port: port, timeout_in_seconds: 2, family: .ip) |
| 51 | // app startup time |
| 52 | _ := <-app.started |
| 53 | } |
| 54 | |
| 55 | fn test_valid_cors() { |
| 56 | x := http.fetch(http.FetchConfig{ |
| 57 | url: localserver |
| 58 | method: .get |
| 59 | header: http.new_header_from_map({ |
| 60 | .origin: allowed_origin |
| 61 | }) |
| 62 | })! |
| 63 | |
| 64 | assert x.status() == .ok |
| 65 | assert x.body == 'index' |
| 66 | } |
| 67 | |
| 68 | fn test_preflight() { |
| 69 | x := http.fetch(http.FetchConfig{ |
| 70 | url: localserver |
| 71 | method: .options |
| 72 | header: http.new_header_from_map({ |
| 73 | .origin: allowed_origin |
| 74 | }) |
| 75 | })! |
| 76 | assert x.status() == .ok |
| 77 | assert x.body == 'ok' |
| 78 | |
| 79 | assert x.header.get(.access_control_allow_origin)! == allowed_origin |
| 80 | if _ := x.header.get(.access_control_allow_credentials) { |
| 81 | assert false, 'Access-Control-Allow-Credentials should not be present the value is `false`' |
| 82 | } |
| 83 | assert x.header.get(.access_control_allow_methods)! == 'GET, HEAD' |
| 84 | } |
| 85 | |
| 86 | fn test_invalid_origin() { |
| 87 | x := http.fetch(http.FetchConfig{ |
| 88 | url: localserver |
| 89 | method: .get |
| 90 | header: http.new_header_from_map({ |
| 91 | .origin: 'https://google.com' |
| 92 | }) |
| 93 | })! |
| 94 | |
| 95 | assert x.status() == .forbidden |
| 96 | } |
| 97 | |
| 98 | fn test_invalid_method() { |
| 99 | x := http.fetch(http.FetchConfig{ |
| 100 | url: '${localserver}/post' |
| 101 | method: .post |
| 102 | header: http.new_header_from_map({ |
| 103 | .origin: allowed_origin |
| 104 | }) |
| 105 | })! |
| 106 | |
| 107 | assert x.status() == .method_not_allowed |
| 108 | } |
| 109 | |