Skip to content

Instantly share code, notes, and snippets.

@michidk
Last active April 21, 2025 16:29
Show Gist options
  • Save michidk/b3676373c3514d36c6a7270be03c796a to your computer and use it in GitHub Desktop.
Save michidk/b3676373c3514d36c6a7270be03c796a to your computer and use it in GitHub Desktop.
Dynamic Zig Webserver
const std = @import("std");
const net = std.net;
const io = std.io;
const mem = std.mem;
const heap = std.heap;
const http = std.http;
const Response = struct {
status: []const u8,
headers: []const u8,
body: []const u8,
allocator: mem.Allocator,
fn init(allocator: mem.Allocator, name: ?[]const u8) !Response {
const name_to_greet = name orelse "Unbekannt";
const body_str = try std.fmt.allocPrint(allocator, "<html><body><h1>Hallo {s}!</h1></body></html>", .{name_to_greet});
return Response{
.status = "200 OK",
.headers = "Content-Type: text/html; charset=utf-8\r\n",
.body = body_str,
.allocator = allocator,
};
}
fn deinit(self: *Response) void {
self.allocator.free(self.body);
}
};
pub fn main() !void {
var gpa = heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
const loopback = try net.Ip4Address.parse("127.0.0.1", 8080);
const localhost = net.Address{ .in = loopback };
var server = try localhost.listen();
defer server.deinit();
std.debug.print("Server gestartet auf http://127.0.0.1:8080\n", .{});
while (true) {
const client = try server.accept();
defer client.stream.close();
var buf: [1024]u8 = undefined;
const bytes_read = try client.stream.read(&buf);
const request_bytes = buf[0..bytes_read];
const res = try http.Server.Request.Head.parse(request_bytes);
std.debug.print("Request target: {s}\n", .{res.target});
// Parse the name parameter from the query string
var name: ?[]const u8 = null;
if (mem.indexOf(u8, res.target, "?name=")) |index| {
const name_start = index + "?name=".len;
const name_end = if (mem.indexOf(u8, res.target[name_start..], "&")) |end_index|
name_start + end_index
else
res.target.len;
name = res.target[name_start..name_end];
}
var response = try Response.init(allocator, name);
defer response.deinit();
try sendResponse(client.stream, &response);
}
}
fn sendResponse(stream: net.Stream, response: *Response) !void {
const writer = stream.writer();
try writer.print("HTTP/1.1 {s}\r\n", .{response.status});
try writer.writeAll(response.headers);
try writer.print("Content-Length: {d}\r\n", .{response.body.len});
try writer.writeAll("\r\n");
try writer.writeAll(response.body);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment