Parse list-based headers
This commit is contained in:
parent
4cb574bc91
commit
b46e82746c
3 changed files with 61 additions and 1 deletions
|
@ -51,6 +51,48 @@ pub const Fields = struct {
|
||||||
return self.unmanaged.get(key);
|
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 {
|
pub fn put(self: *Fields, key: []const u8, val: []const u8) !void {
|
||||||
const key_clone = try self.allocator.alloc(u8, key.len);
|
const key_clone = try self.allocator.alloc(u8, key.len);
|
||||||
std.mem.copy(u8, key_clone, key);
|
std.mem.copy(u8, key_clone, key);
|
||||||
|
|
|
@ -115,7 +115,7 @@ fn parseHeaders(allocator: std.mem.Allocator, reader: anytype) !Fields {
|
||||||
|
|
||||||
const value = std.mem.trim(u8, line[name.len + 1 ..], " \t");
|
const value = std.mem.trim(u8, line[name.len + 1 ..], " \t");
|
||||||
|
|
||||||
try headers.put(name, value);
|
try headers.append(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return headers;
|
return headers;
|
||||||
|
|
|
@ -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" }},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue