| 1 | // vtest build: !windows // fasthttp.Server.run is not implemented on windows yet |
| 2 | import log |
| 3 | import veb |
| 4 | import time |
| 5 | import net |
| 6 | import x.json2 |
| 7 | import net.http |
| 8 | |
| 9 | const port = 31228 |
| 10 | |
| 11 | pub struct Context { |
| 12 | veb.Context |
| 13 | } |
| 14 | |
| 15 | pub struct App { |
| 16 | pub mut: |
| 17 | started chan bool |
| 18 | } |
| 19 | |
| 20 | pub fn (mut app App) before_accept_loop() { |
| 21 | app.started <- true |
| 22 | } |
| 23 | |
| 24 | @['/data/:filename'; post] |
| 25 | fn (mut app App) data(mut ctx Context, filename string) veb.Result { |
| 26 | content_type := ctx.get_header(http.CommonHeader.content_type) or { return ctx.no_content() } |
| 27 | f := http.FileData{ |
| 28 | filename: filename |
| 29 | content_type: content_type |
| 30 | data: ctx.req.data |
| 31 | } |
| 32 | log.info('Received ${filename} with content_type ${content_type} and length ${f.data.len}') |
| 33 | return ctx.json(f) |
| 34 | } |
| 35 | |
| 36 | const svg_image_content = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-8 -308 316 316" width="316" height="316"><g fill-opacity="0" stroke="#000" xmlns="http://www.w3.org/2000/svg"><path xmlns="http://www.w3.org/2000/svg" d="M0 0 l -1.8369701987210297e-14 -100 m -1.8369701987210297e-14 -100 l -1.8369701987210297e-14 -100 l 100 -2.4492935982947064e-14 m 100 -2.4492935982947064e-14 l 100 -2.4492935982947064e-14 l 3.061616997868383e-14 100 m 3.061616997868383e-14 100 l 3.061616997868383e-14 100 l -100 3.6739403974420595e-14 m -100 3.6739403974420595e-14 l -100 3.6739403974420595e-14" stroke="#000000" stroke-width="5"></path></g></svg>' |
| 37 | |
| 38 | fn test_veb_app_start() { |
| 39 | log.info('starting watchdog ...') |
| 40 | spawn fn () { |
| 41 | log.info('watchdog running') |
| 42 | time.sleep(10 * time.second) |
| 43 | log.info('exiting...') |
| 44 | exit(0) |
| 45 | }() |
| 46 | mut app := &App{} |
| 47 | spawn veb.run_at[App, Context](mut app, port: port) |
| 48 | _ := <-app.started |
| 49 | log.info('app started') |
| 50 | } |
| 51 | |
| 52 | fn test_make_request() { |
| 53 | mut client := net.dial_tcp('127.0.0.1:${port}')! |
| 54 | defer { client.close() or {} } |
| 55 | client.write_string('POST /data/Seeker.svg HTTP/1.1\r |
| 56 | Host: localhost:8090\r |
| 57 | User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0\r |
| 58 | Accept: */*\r |
| 59 | Accept-Language: en-US,en;q=0.5\r |
| 60 | Accept-Encoding: gzip, deflate, br, zstd\r |
| 61 | Content-Type: image/svg+xml\r |
| 62 | Content-Length: 618\r |
| 63 | Origin: null\r |
| 64 | Connection: close\r |
| 65 | Sec-Fetch-Dest: empty\r |
| 66 | Sec-Fetch-Mode: cors\r |
| 67 | Sec-Fetch-Site: cross-site\r |
| 68 | Priority: u=4\r |
| 69 | \r |
| 70 | ')! // " |
| 71 | |
| 72 | time.sleep(25 * time.millisecond) |
| 73 | client.write_string(svg_image_content)! |
| 74 | mut res := []u8{} |
| 75 | mut buf := []u8{len: 512} |
| 76 | for { |
| 77 | read_len := client.read(mut buf) or { break } |
| 78 | if read_len == 0 { |
| 79 | break |
| 80 | } |
| 81 | res << buf[0..read_len] |
| 82 | } |
| 83 | response := res.bytestr() |
| 84 | assert response.starts_with('HTTP/1.1 200 OK') |
| 85 | assert response.contains('Content-Length: 706') |
| 86 | assert response.contains('Content-Type: application/json') |
| 87 | payload := response.all_after('\r\n\r\n') |
| 88 | r := json2.decode[http.FileData](payload)! |
| 89 | dump(r.filename) |
| 90 | dump(r.content_type) |
| 91 | assert r.filename == 'Seeker.svg' |
| 92 | assert r.content_type == 'image/svg+xml' |
| 93 | assert r.data.starts_with('<svg xmlns=') |
| 94 | assert r.data.ends_with('</svg>') |
| 95 | assert r.data == svg_image_content |
| 96 | } |
| 97 | |