Parse list-based headers

This commit is contained in:
jaina heartles 2022-11-05 01:54:00 -07:00
parent 4cb574bc91
commit b46e82746c
3 changed files with 61 additions and 1 deletions

View file

@ -51,6 +51,48 @@ pub const Fields = struct {
return self.unmanaged.get(key);
}
pub const ListIterator = struct {
remaining: []const u8,
fn extractElement(self: *ListIterator) ?[]const u8 {
if (self.remaining.len == 0) return null;
var start: usize = 0;
var is_quoted = false;
const end = for (self.remaining) |ch, i| {
if (start == i and std.ascii.isWhitespace(ch)) {
start += 1;
} else if (ch == '"') {
is_quoted = !is_quoted;
}
if (ch == ',' and !is_quoted) {
break i;
}
} else self.remaining.len;
const str = self.remaining[start..end];
if (end == self.remaining.len) {
self.remaining = "";
} else {
self.remaining = self.remaining[end + 1 ..];
}
return std.mem.trim(u8, str, " \t");
}
pub fn next(self: *ListIterator) ?[]const u8 {
while (self.extractElement()) |elem| {
if (elem.len != 0) return elem;
}
return null;
}
};
pub fn getList(self: Fields, key: []const u8) ?ListIterator {
return if (self.unmanaged.get(key)) |hdr| ListIterator{ .remaining = hdr } else null;
}
pub fn put(self: *Fields, key: []const u8, val: []const u8) !void {
const key_clone = try self.allocator.alloc(u8, key.len);
std.mem.copy(u8, key_clone, key);

View file

@ -115,7 +115,7 @@ fn parseHeaders(allocator: std.mem.Allocator, reader: anytype) !Fields {
const value = std.mem.trim(u8, line[name.len + 1 ..], " \t");
try headers.put(name, value);
try headers.append(name, value);
}
return headers;

View file

@ -262,3 +262,21 @@ test "HTTP/1.x parse - bad requests" {
.{},
));
}
test "HTTP/1.x parse - Headers" {
try test_case.parse(
toCrlf(
\\GET /url/abcd HTTP/1.1
\\Content-Type: application/json
\\Content-Type: application/xml
\\
\\
),
.{
.protocol = .http_1_1,
.method = .GET,
.uri = "/url/abcd",
.headers = &.{.{ "Content-Type", "application/json, application/xml" }},
},
);
}