Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VWeb; No function to send raw data #21743

Closed
wahur666 opened this issue Jun 26, 2024 · 4 comments
Closed

VWeb; No function to send raw data #21743

wahur666 opened this issue Jun 26, 2024 · 4 comments
Labels
Bug This tag is applied to issues which reports bugs.

Comments

@wahur666
Copy link
Contributor

wahur666 commented Jun 26, 2024

Describe the bug

With a previous version of vweb I wrote a code, to serve video files.
I used this code:

app.Context.set_status(206, 'Partial Content')
app.Context.add_header('Content-Range', 'bytes $start-$end/$video_size')
app.Context.add_header('Accept-Ranges', 'bytes')
app.Context.add_header('Connection', 'Keep-Alive')
app.Context.set_content_type('video/mp4')
return app.ok(buf.bytestr())

And worked.

Now there is a fix, whereas the ok function now sets the status

pub fn (mut ctx Context) ok(s string) Result {
	ctx.set_status(200, 'OK')
	ctx.send_response_to_client(ctx.content_type, s)
	return Result{}
}

Which is working as expected, but this eliminated the possibility of sending other kind of code.

I looked at all the other function, which can send code, back to the client, with the return type vweb.Result, and found none which can do what I need.

I saw that here is the send_response_to_client function, which will do what I need, but that does not return the vweb.Result type.

I propose to add a send or send_raw or something like this function, to accommodate this use-case above.

Reproduction Steps

import vweb
import net.http
import os
import math

struct App {
	vweb.Context
}

fn main() {
	mut app := &App{}
	vweb.run_at(app, vweb.RunParams{
		port: 8081
		nr_workers: 1
	}) or {panic(err)}
}

pub fn (mut app App) index() vweb.Result {
	return $vweb.html()
}

pub fn (mut app App) video() vweb.Result {
	range_header := app.req.header.get(http.CommonHeader.range) or { '' }
	if range_header == '' {
		app.set_status(400, 'Bad Request')
		println("no header")
		return app.text('')
	}
	video_path := 'path/to/mp4/file' #add a local file here 
	video_size := u64(os.file_size('./' + video_path))
	chunk_size := u64(math.pow10(6))
	println("${range_header}")
	start := range_header.split('=')[1].split('-')[0].u64()
	println("$start")
	end := math.min(start + chunk_size, video_size - 1)
	content_length := end - start + 1

	mut f := os.open('./' + video_path) or { panic(err) }
	defer {
		f.close()
	}

	mut buf := []u8{len: int(content_length)}
	f.read_bytes_into(start, mut buf) or { 0 }

	app.Context.set_status(206, 'Partial Content')
	app.Context.add_header('Content-Range', 'bytes $start-$end/$video_size')
	app.Context.add_header('Accept-Ranges', 'bytes')
	app.Context.set_content_type('video/mp4')
	return app.send(buf.bytestr())
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 40px auto;
            max-width: 650px;
            background-color: #444;
        }
    </style>
</head>
<body>
    <video id="video-player" width="650" controls autoplay>
        <source src="/video" type="video/mp4">
    </video>
</body>
</html>

Expected Behavior

Can send arbitrary mimetype and status code

Current Behavior

Cant send arbitrary mimetype and status code

Possible Solution

pub fn (mut ctx Context) send(s string) Result {
	ctx.send_response_to_client(ctx.content_type, s)
	return Result {}
}

Additional Information/Context

Video streaming and using Partial Content 206 and video/mp4

V version

V 0.4.6 100b3b0.dfdd752

Environment details (OS name and version, etc.)

OS: windows, Microsoft Windows 11 Pro v22631 64-bit
Processor: 6 cpus, 64bit, little endian,

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

@wahur666 wahur666 added the Bug This tag is applied to issues which reports bugs. label Jun 26, 2024
@Casper64
Copy link
Member

For this usecase you can call send_response_to_client and return veb.no_result: https://github.com/vlang/v/blob/master/vlib/veb/README.md#empty-result

If your usecase is sending a file you can also use veb's new ctx.file method
https://github.com/vlang/v/blob/master/vlib/veb/README.md#sending-files

The file method sends the data in a stream towards the browser and will be faster than your current implementation.

pub fn (mut app App) video(mut ctx Context) vweb.Result {
    return ctx.file('path/to/mp4/file')
}

(haven't tested the code)

@wahur666
Copy link
Contributor Author

wahur666 commented Aug 5, 2024

For this usecase you can call send_response_to_client and return veb.no_result: https://github.com/vlang/v/blob/master/vlib/veb/README.md#empty-result

If your usecase is sending a file you can also use veb's new ctx.file method https://github.com/vlang/v/blob/master/vlib/veb/README.md#sending-files

The file method sends the data in a stream towards the browser and will be faster than your current implementation.

pub fn (mut app App) video(mut ctx Context) vweb.Result {
    return ctx.file('path/to/mp4/file')
}

(haven't tested the code)

Thank you for the response.

  1. The veb and vweb Result types are not compatible...
  2. If you send file with the following code
pub fn (mut app App) video2() vweb.Result {
    return app.Context.file('path/to/mp4/file')
}

Yes, indeed it is "faster" but the seeking option for the video file not working now...

So thank you, but your answer is not good. On the other hand, I found the workaround this way:

app.Context.send_response_to_client('video/mp4', buf.bytestr())
return vweb.not_found()

@JalonSolov
Copy link
Contributor

vweb is deprecated. veb is the newer web code. The suggestion was for veb, not vweb.

@wahur666
Copy link
Contributor Author

wahur666 commented Aug 5, 2024

vweb is deprecated. veb is the newer web code. The suggestion was for veb, not vweb.

I rewrote just this part, to veb and the file still not sent as partial, and not seekable, sorry still not good for me usecase. I will rewrite the rest of it too, but I got my answer. Thank you anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug This tag is applied to issues which reports bugs.
Projects
None yet
Development

No branches or pull requests

3 participants