mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
x.vweb: fix fsanitize-address test for SSE, improve documentation on the usage of takeover_conn
(#20249)
This commit is contained in:
parent
06a536eff2
commit
ada9efd825
6 changed files with 30 additions and 11 deletions
|
@ -805,6 +805,16 @@ When this function is called you are free to do anything you want with the TCP
|
|||
connection and vweb will not interfere. This means that we are responsible for
|
||||
sending a response over the connection and closing it.
|
||||
|
||||
### Empty Result
|
||||
|
||||
Sometimes you want to send the response in another thread, for example when using
|
||||
[Server Sent Events](sse/README.md). When you are sure that a response will be sent
|
||||
over the TCP connection you can return `vweb.no_result()`. This function does nothinng
|
||||
and returns an empty `vweb.Result` struct, letting vweb know that we sent a response ourself.
|
||||
|
||||
> **Note:**
|
||||
> It is important to call `ctx.takeover_conn` before you spawn a thread
|
||||
|
||||
**Example:**
|
||||
```v
|
||||
module main
|
||||
|
@ -825,11 +835,14 @@ pub fn (app &App) index(mut ctx Context) vweb.Result {
|
|||
|
||||
@['/long']
|
||||
pub fn (app &App) long_response(mut ctx Context) vweb.Result {
|
||||
// let vweb know that the connection should not be closed
|
||||
ctx.takeover_conn()
|
||||
// use spawn to handle the connection in another thread
|
||||
// if we don't the whole web server will block for 10 seconds,
|
||||
// since vweb is singlethreaded
|
||||
spawn handle_connection(mut ctx.conn)
|
||||
return ctx.takeover_conn()
|
||||
// we will send a custom response ourself, so we can safely return an empty result
|
||||
return vweb.no_result()
|
||||
}
|
||||
|
||||
fn handle_connection(mut conn net.TcpConn) {
|
||||
|
|
|
@ -276,9 +276,8 @@ pub fn (mut ctx Context) set_content_type(mime string) {
|
|||
// send over the connetion and you can send multiple responses.
|
||||
// This function is usefull when you want to keep the connection alive and/or
|
||||
// send multiple responses. Like with the SSE.
|
||||
pub fn (mut ctx Context) takeover_conn() Result {
|
||||
pub fn (mut ctx Context) takeover_conn() {
|
||||
ctx.takeover = true
|
||||
return Result{}
|
||||
}
|
||||
|
||||
// user_agent returns the user-agent header for the current client
|
||||
|
|
|
@ -11,9 +11,9 @@ With SSE we want to keep the connection open, so we are able to
|
|||
keep sending events to the client. But if we hold the connection open indefinitely
|
||||
vweb isn't able to process any other requests.
|
||||
|
||||
We can let vweb know that it can continue
|
||||
processing other requests and that we will handle the connection ourself by
|
||||
returning `ctx.takeover_conn()`. Vweb will not close the connection and we can handle
|
||||
We can let vweb know that it can continue processing other requests and that we will
|
||||
handle the connection ourself by calling `ctx.takeover_conn()` and and returning an empty result
|
||||
with `vweb.no_result()`. Vweb will not close the connection and we can handle
|
||||
the connection in a seperate thread.
|
||||
|
||||
**Example:**
|
||||
|
@ -22,10 +22,12 @@ import x.vweb.sse
|
|||
|
||||
// endpoint handler for SSE connections
|
||||
fn (app &App) sse(mut ctx Context) vweb.Result {
|
||||
// let vweb know that the connection should not be closed
|
||||
ctx.takeover_conn()
|
||||
// handle the connection in a new thread
|
||||
spawn handle_sse_conn(mut ctx)
|
||||
// let vweb know that the connection should not be closed
|
||||
return ctx.takeover_conn()
|
||||
// we will send a custom response ourself, so we can safely return an empty result
|
||||
return vweb.no_result()
|
||||
}
|
||||
|
||||
fn handle_sse_conn(mut ctx Context) {
|
||||
|
|
|
@ -37,7 +37,6 @@ pub mut:
|
|||
|
||||
// start an SSE connection
|
||||
pub fn start_connection(mut ctx vweb.Context) &SSEConnection {
|
||||
ctx.takeover_conn()
|
||||
ctx.res.header.set(.connection, 'keep-alive')
|
||||
ctx.res.header.set(.cache_control, 'no-cache')
|
||||
ctx.send_response_to_client('text/event-stream', '')
|
||||
|
|
|
@ -14,12 +14,12 @@ pub struct Context {
|
|||
pub struct App {}
|
||||
|
||||
fn (app &App) sse(mut ctx Context) vweb.Result {
|
||||
ctx.takeover_conn()
|
||||
spawn handle_sse_conn(mut ctx)
|
||||
return ctx.takeover_conn()
|
||||
return vweb.no_result()
|
||||
}
|
||||
|
||||
fn handle_sse_conn(mut ctx Context) {
|
||||
// pass vweb.Context
|
||||
mut sse_conn := sse.start_connection(mut ctx.Context)
|
||||
|
||||
for _ in 0 .. 3 {
|
||||
|
|
|
@ -20,6 +20,12 @@ pub type RawHtml = string
|
|||
@[noinit]
|
||||
pub struct Result {}
|
||||
|
||||
// no_result does nothing, but returns `vweb.Result`. Only use it when you are sure
|
||||
// a response will be send over the connection, or in combination with `Context.takeover_conn`
|
||||
pub fn no_result() Result {
|
||||
return Result{}
|
||||
}
|
||||
|
||||
pub const methods_with_form = [http.Method.post, .put, .patch]
|
||||
|
||||
pub const headers_close = http.new_custom_header_from_map({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue