Skip to content

Commit

Permalink
Streaming API in server.v
Browse files Browse the repository at this point in the history
  • Loading branch information
alii committed Dec 29, 2024
1 parent 4330626 commit 14a68ea
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 13 deletions.
Binary file modified packages/node/binding.node
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/node/modules/picoev
Submodule picoev updated 2 files
+46 −58 picoev.v
+3 −19 socket_util.c.v
2 changes: 1 addition & 1 deletion packages/node/modules/picohttpparser
Submodule picohttpparser updated 3 files
+73 −0 bodyreader.v
+18 −0 request.v
+2 −14 response.c.v
43 changes: 32 additions & 11 deletions packages/node/modules/server/server.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,55 @@ fn callback(data voidptr, req picohttpparser.Request, mut res picohttpparser.Res
eprintln('Method not allowed: ${req.method}')
res.status(405)
res.header('Content-Type', 'application/json')
res.header('Connection', 'close')
res.header('Connection', if req.client_wants_keep_alive() { 'keep-alive' } else { 'close' })
res.body('{"error":"Only POST method is allowed"}')
if res.end() < 0 {
eprintln('Failed to send error response')
}
return
}

// With the new streaming API, the body is already accumulated in req.body
// by the time this callback is called
if req.body.len == 0 {
// Get the body reader if available
mut body := ''
if mut br := req.get_body_reader() {
body_bytes := br.read_all() or {
eprintln('Failed to read body: ${err}')
res.status(400)
res.header('Content-Type', 'application/json')
res.header('Connection', 'close')
res.body('{"error":"Failed to read request body"}')
if res.end() < 0 {
eprintln('Failed to send error response')
}
return
}
body = body_bytes.bytestr()
}

if body.len == 0 {
eprintln('No body provided')
res.status(400)
res.header('Content-Type', 'application/json')
res.header('Connection', 'close')
res.header('Connection', if req.client_wants_keep_alive() { 'keep-alive' } else { 'close' })
res.body('{"error":"No body provided"}')
if res.end() < 0 {
eprintln('Failed to send error response')
}
return
}

eprintln('Received complete body: ${req.body} ${req.body.len}')
eprintln('Received complete body: ${body} ${body.len}')
res.status(200)
res.header('Content-Type', 'text/plain')
res.header('Connection', 'close')
res.body(req.body)
eprintln('Response prepared')
res.header('Connection', if req.client_wants_keep_alive() { 'keep-alive' } else { 'close' })
res.body(body)
if res.end() < 0 {
eprintln('Failed to send response')
}
}

// start creates and starts a new HTTP server on the specified port
pub fn start(port int) ! {
eprintln('Starting server on port ${port}')
mut s := picoev.new(
port: port,
cb: callback,
Expand All @@ -45,6 +67,5 @@ pub fn start(port int) ! {
max_write: 8192
)!

eprintln('Server initialized, starting event loop')
s.serve()
}
33 changes: 33 additions & 0 deletions packages/node/modules/socket/socket.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module socket

$if !windows {
#include <sys/socket.h>
}

// read_socket reads from a socket into a buffer
@[inline]
pub fn read_socket(fd int, buffer &u8, max_len int, offset int) int {
// use `recv` instead of `read` for windows compatibility
return unsafe { C.recv(fd, buffer + offset, max_len - offset, 0) }
}

// is_fatal_error returns true if the socket error is fatal
@[inline]
pub fn is_fatal_error(fd int) bool {
if C.errno == C.EAGAIN {
// try again later
return false
}
$if windows {
if C.errno == C.WSAEWOULDBLOCK {
// try again later
return false
}
} $else {
if C.errno == C.EWOULDBLOCK {
// try again later
return false
}
}
return true
}

0 comments on commit 14a68ea

Please sign in to comment.