| ... | @@ -299,7 +299,7 @@ pub const Request = struct { | ... | @@ -299,7 +299,7 @@ pub const Request = struct { |
| 299 | } | 299 | } |
| 300 | }; | 300 | }; |
| 301 | | 301 | |
| 302 | pub fn iterateHeaders(r: Request) http.HeaderIterator { | 302 | pub fn iterateHeaders(r: *Request) http.HeaderIterator { |
| 303 | return http.HeaderIterator.init(r.server.read_buffer[0..r.head_end]); | 303 | return http.HeaderIterator.init(r.server.read_buffer[0..r.head_end]); |
| 304 | } | 304 | } |
| 305 | | 305 | |
| ... | @@ -363,76 +363,6 @@ pub const Request = struct { | ... | @@ -363,76 +363,6 @@ pub const Request = struct { |
| 363 | try testing.expectEqual(null, it.next()); | 363 | try testing.expectEqual(null, it.next()); |
| 364 | } | 364 | } |
| 365 | | 365 | |
| 366 | /// Retrieves the value of a specified HTTP header from a Request struct. | | |
| 367 | /// | | |
| 368 | /// This function searches for a header with a name matching the provided string, | | |
| 369 | /// ignoring case. If found, it returns the header's value. If not found, it | | |
| 370 | /// returns null. | | |
| 371 | /// | | |
| 372 | /// Note: If multiple headers with the same name are present, this function | | |
| 373 | /// will return the value of the first matching header encountered. | | |
| 374 | /// | | |
| 375 | /// For accessing duplicate headers or iterating through all headers, | | |
| 376 | /// use the `iterateHeaders()` method directly. | | |
| 377 | pub fn getHeader(r: Request, s: []const u8) ?[]const u8 { | | |
| 378 | var iter = r.iterateHeaders(); | | |
| 379 | while (iter.next()) |header| { | | |
| 380 | if (std.ascii.eqlIgnoreCase(s, header.name)) { | | |
| 381 | return header.value; | | |
| 382 | } | | |
| 383 | } | | |
| 384 | return null; | | |
| 385 | } | | |
| 386 | | | |
| 387 | test getHeader { | | |
| 388 | const request_bytes = "GET /hi HTTP/1.0\r\n" ++ | | |
| 389 | "content-tYpe: text/plain\r\n" ++ | | |
| 390 | "content-Length:10\r\n" ++ | | |
| 391 | "expeCt: 100-continue \r\n" ++ | | |
| 392 | "TRansfer-encoding:\tdeflate, chunked \r\n" ++ | | |
| 393 | "connectioN:\t keep-alive \r\n\r\n"; | | |
| 394 | var read_buffer: [500]u8 = undefined; | | |
| 395 | | | |
| 396 | @memcpy(read_buffer[0..request_bytes.len], request_bytes); | | |
| 397 | var server: Server = .{ | | |
| 398 | .connection = undefined, | | |
| 399 | .state = .ready, | | |
| 400 | .read_buffer = &read_buffer, | | |
| 401 | .read_buffer_len = request_bytes.len, | | |
| 402 | .next_request_start = 0, | | |
| 403 | }; | | |
| 404 | const request: Request = .{ | | |
| 405 | .server = &server, | | |
| 406 | .head_end = request_bytes.len, | | |
| 407 | .head = undefined, | | |
| 408 | .reader_state = undefined, | | |
| 409 | }; | | |
| 410 | | | |
| 411 | // Test 1: Existing header with case-insensitive match | | |
| 412 | try testing.expectEqualStrings("text/plain", getHeader(request, "content-type").?); | | |
| 413 | | | |
| 414 | // Test 2: Existing header with exact case match | | |
| 415 | try testing.expectEqualStrings("10", getHeader(request, "content-Length").?); | | |
| 416 | | | |
| 417 | // Test 3: Existing header with leading/trailing whitespace | | |
| 418 | try testing.expectEqualStrings("100-continue", getHeader(request, "expect").?); | | |
| 419 | | | |
| 420 | // Test 4: Existing header with tab separator | | |
| 421 | try testing.expectEqualStrings("deflate, chunked", getHeader(request, "Transfer-encoding").?); | | |
| 422 | | | |
| 423 | // Test 5: Non-existent header | | |
| 424 | try testing.expectEqual(@as(?[]const u8, null), getHeader(request, "User-Agent")); | | |
| 425 | | | |
| 426 | // Test 6: Case-insensitive match for header name | | |
| 427 | try testing.expectEqualStrings("keep-alive", getHeader(request, "CONNECTION").?); | | |
| 428 | | | |
| 429 | // Test 7: Partial header name match (should fail) | | |
| 430 | try testing.expectEqual(@as(?[]const u8, null), getHeader(request, "content")); | | |
| 431 | | | |
| 432 | // Test 8: Empty header name (should return null) | | |
| 433 | try testing.expectEqual(@as(?[]const u8, null), getHeader(request, "")); | | |
| 434 | } | | |
| 435 | | | |
| 436 | pub const RespondOptions = struct { | 366 | pub const RespondOptions = struct { |
| 437 | version: http.Version = .@"HTTP/1.1", | 367 | version: http.Version = .@"HTTP/1.1", |
| 438 | status: http.Status = .ok, | 368 | status: http.Status = .ok, |