srctree

Gregory Mullen parent a16b99cc 01126b1a
add usable errors to websocket & improve example

inlinesplit
examples/websocket.zig added: 33, removed: 19, total 14
@@ -10,20 +10,20 @@ const Root = struct {
 
pub fn index(frame: *verse.Frame) verse.Router.Error!void {
var buffer: [0xffffff]u8 = undefined;
const page = try print(&buffer, page_html, .{"page never generated"});
const page = try bufPrint(&buffer, page_html, .{"page never generated"});
 
try frame.sendHTML(.ok, page);
}
 
fn socket(frame: *verse.Frame) verse.Router.Error!void {
var ws = frame.acceptWebsocket() catch unreachable;
var ws = frame.acceptWebsocket() catch return error.DataMissing;
 
for (0..10) |i| {
var buffer: [0xff]u8 = undefined;
ws.send(print(&buffer, "Iteration {}\n", .{i}) catch unreachable) catch unreachable;
try ws.send(try bufPrint(&buffer, "Iteration {}\n", .{i}));
std.time.sleep(1_000_000_000);
var read_buffer: [0x4000]u8 align(8) = undefined;
const msg = ws.recieve(&read_buffer) catch unreachable;
const msg = ws.recieve(&read_buffer) catch return error.BrokenPipe;
std.debug.print("msg: {} -- {} -- {s}\n", .{ msg.header, msg.msg.len, msg.msg });
}
std.debug.print("Socket Example Done\n", .{});
@@ -82,4 +82,4 @@ pub fn main() !void {
 
const std = @import("std");
const verse = @import("verse");
const print = std.fmt.bufPrint;
const bufPrint = std.fmt.bufPrint;
 
src/websocket.zig added: 33, removed: 19, total 14
@@ -2,17 +2,32 @@ frame: *Frame,
 
const Websocket = @This();
 
pub fn accept(frame: *Frame) !Websocket {
pub const Error = WriteError || MemError || ReadError;
 
pub const MemError = error{
OutOfMemory,
};
 
pub const WriteError = error{
IOWriteFailure,
} || MemError;
 
pub const ReadError = error{
IOReadFailure,
RequiredHeaderMissing,
} || MemError;
 
pub fn accept(frame: *Frame) Error!Websocket {
const key = if (frame.request.headers.getCustom("Sec-WebSocket-Key")) |key|
key.list[0]
else
return error.InvalidWebsocketRequest;
return error.RequiredHeaderMissing;
 
try respond(frame, key);
return Websocket{ .frame = frame };
}
 
fn respond(f: *Frame, key: []const u8) !void {
fn respond(f: *Frame, key: []const u8) WriteError!void {
f.status = .switching_protocols;
f.content_type = null;
 
@@ -28,26 +43,25 @@ fn respond(f: *Frame, key: []const u8) !void {
const accept_key = base64.encode(&encoded, &digest);
try f.headers.addCustom("Sec-WebSocket-Accept", accept_key);
 
try f.sendHeaders();
try f.sendRawSlice("\r\n");
f.sendHeaders() catch return error.IOWriteFailure;
f.sendRawSlice("\r\n") catch return error.IOWriteFailure;
}
 
pub fn send(ws: Websocket, msg: []const u8) !void {
pub fn send(ws: Websocket, msg: []const u8) WriteError!void {
const m = Message.init(msg, .text);
const vec = m.toVec();
 
_ = switch (ws.frame.downstream) {
.zwsgi, .http => |stream| try stream.writev(vec[0..3]),
else => {},
};
.zwsgi, .http => |stream| stream.writev(m.toVec()[0..3]),
else => unreachable,
} catch return error.IOWriteFailure;
}
 
pub fn recieve(ws: *Websocket, buffer: []align(8) u8) !Message {
pub fn recieve(ws: *Websocket, buffer: []align(8) u8) Error!Message {
var reader = switch (ws.frame.downstream) {
.zwsgi, .http => |stream| stream.reader(),
else => unreachable,
};
return try Message.read(reader.any(), buffer);
return Message.read(reader.any(), buffer) catch error.IOReadFailure;
}
 
pub const Message = struct {