Remove allocs in Headers.getAll()

Provide `Headers.getAllIterator()` to iterate over matching headers, use
this to iterate through `Accept-Encoding` headers in
CompressionMiddleware.
This commit is contained in:
Bob Farrell 2024-06-01 17:09:49 +01:00
parent 7339641401
commit 3875ffbdfb
2 changed files with 47 additions and 2 deletions

View File

@ -59,6 +59,10 @@ pub fn getFirstValue(self: *const Headers, name: []const u8) ?[]const u8 {
return self.get(name);
}
pub fn count(self: Headers) usize {
return self.httpz_headers.len;
}
/// Add `name` and `value` to headers.
pub fn append(self: *Headers, name: []const u8, value: []const u8) !void {
if (self.httpz_headers.len >= self.httpz_headers.keys.len) return error.JetzigTooManyHeaders;
@ -75,6 +79,46 @@ pub fn append(self: *Headers, name: []const u8, value: []const u8) !void {
self.httpz_headers.add(header.name, header.value);
}
const Iterator = struct {
position: usize = 0,
headers: Headers,
filter_name: ?[]const u8 = null,
pub fn next(self: *Iterator) ?Header {
const header_count = self.headers.count();
if (self.position >= header_count) {
return null;
}
const start = self.position;
var buf: [jetzig.config.get(u16, "max_bytes_header_name")]u8 = undefined;
const filter_name = if (self.filter_name) |name| std.ascii.lowerString(&buf, name) else null;
for (start..header_count) |index| {
const key = self.headers.httpz_headers.keys[start + index];
const value = self.headers.httpz_headers.values[start + index];
self.position += 1;
if (filter_name) |name| {
if (std.mem.eql(u8, name, key)) {
return .{ .name = key, .value = value };
}
} else {
return .{ .name = key, .value = value };
}
}
return null;
}
};
pub fn getAllIterator(self: Headers, name: []const u8) Iterator {
return .{ .headers = self, .filter_name = name };
}
pub fn iterator(self: Headers) Iterator {
return .{ .headers = self };
}
test "append (deprecated)" {
const allocator = std.testing.allocator;
var httpz_headers = try httpz.key_value.KeyValue.init(allocator, 10);

View File

@ -44,8 +44,9 @@ pub fn beforeResponse(request: *jetzig.http.Request, response: *jetzig.http.Resp
}
fn detectEncoding(request: *const jetzig.http.Request) ?Encoding {
for (request.headers.getAll("Accept-Encoding")) |encodings| {
var it = std.mem.tokenizeScalar(u8, encodings, ',');
var headers_it = request.headers.getAllIterator("Accept-Encoding");
while (headers_it.next()) |header| {
var it = std.mem.tokenizeScalar(u8, header.value, ',');
while (it.next()) |param| {
inline for (@typeInfo(Encoding).Enum.fields) |field| {
if (std.mem.eql(u8, field.name, jetzig.util.strip(param))) {