Skip to content

Commit

Permalink
Streaming API
Browse files Browse the repository at this point in the history
  • Loading branch information
alii committed Dec 29, 2024
1 parent 1eec312 commit 4330626
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 18 deletions.
2 changes: 2 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ You can use a new node feature to run typescript files:
Do NOT use node-gyp, bindings.gyp or anything like that. I want
to always use a simple build pipeline, and the node-api-headers
header files.

Do not use globals in vlang. Unsafe code is allowed.
Binary file modified packages/node/binding.node
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/node/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# v -d no_backtrace -shared binding.v -o binding.node -autofree
v -d no_backtrace -enable-globals -shared binding.v -o binding.node -cg
v -d no_backtrace -shared binding.v -o binding.node -cg

mv binding.node.dylib binding.node
10 changes: 10 additions & 0 deletions packages/node/example.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import {spawn} from 'node:child_process';
import {createRequire} from 'node:module';

const require = createRequire(import.meta.url);

const binding = require('./binding.node');

// Spawn a process that will kill this one after 5s
const thisPid = process.pid;
spawn('node', ['-e', `setTimeout(() => { process.kill(${thisPid}, 'SIGKILL'); }, 10_000);`]);

// Redirect stderr to console
process.stderr.on('data', data => {
console.error(data.toString());
});

console.log('Starting server...');
binding.server(8080);
console.log(`Server started! Try visiting http://localhost:8080`);
2 changes: 1 addition & 1 deletion packages/node/modules/picoev
Submodule picoev updated 2 files
+217 −45 picoev.v
+5 −2 socket_util.c.v
2 changes: 1 addition & 1 deletion packages/node/modules/picohttpparser
Submodule picohttpparser updated 2 files
+41 −230 request.v
+46 −6 response.c.v
37 changes: 22 additions & 15 deletions packages/node/modules/server/server.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,48 @@ module server
import picoev
import picohttpparser

// Request handler callback for the HTTP server
fn callback(data voidptr, req picohttpparser.Request, mut res picohttpparser.Response) {
eprintln('Handling request: ${req.method} ${req.path}')
if req.method != 'POST' {
eprintln('Method not allowed: ${req.method}')
res.status(405)
res.header('Content-Type', 'application/json')
res.header('Connection', 'close')
res.body('{"error":"Only POST method is allowed"}')
res.end()
return
}

mut reader := req.get_body_reader() or {
// 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 {
eprintln('No body provided')
res.status(400)
res.header('Content-Type', 'application/json')
res.header('Connection', 'close')
res.body('{"error":"No body provided"}')
res.end()
return
}

// Read the entire body
body := reader.read_all() or {
res.status(400)
res.body('{"error":"Failed to read body: ${err}"}')
res.end()
return
}

println('Read complete body: ${body.bytestr()}')
eprintln('Received complete body: ${req.body} ${req.body.len}')
res.status(200)
res.body(body.bytestr())
res.end()
res.header('Content-Type', 'text/plain')
res.header('Connection', 'close')
res.body(req.body)
eprintln('Response prepared')
}

// 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,
timeout_secs: 30
timeout_secs: 30,
max_read: 8192,
max_write: 8192
)!

eprintln('Server initialized, starting event loop')
s.serve()
}

0 comments on commit 4330626

Please sign in to comment.