code wiki / (root) / nx_http_header_find_test.nx

nx_http_header_find_test.nx source

↩ module page · 142 lines · 5942 B

1// nx_http_header_find_test.nx -- smoke for case-insensitive header search. 2// 3// expect_exit: 0 4// 5// license_tier: ORIGINAL 6 7import "nx_syscalls_x86_64.nx" 8import "nx_http_header_find.nx" 9 10func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 { 11 var i: i64 = 0 12 while i < n { 13 if a[i] != b[i] { return 0 } 14 i = i + 1 15 } 16 return 1 17} 18 19func emit(buf: *u8, off: i64, s: *u8) -> i64 { 20 var i: i64 = 0 21 while s[i] != 0 { 22 buf[off + i] = s[i] 23 i = i + 1 24 } 25 return off + i 26} 27 28func main() -> i64 { 29 // ---- Verdict enum ---- 30 if nxhf_verdict_is_valid(NXHF_FOUND) != 1 { return 1 } 31 if nxhf_verdict_is_valid(NXHF_VERDICT_N) != 0 { return 2 } 32 if bytes_eq(nxhf_verdict_name(NXHF_FOUND), "FOUND" as *u8, 5) != 1 { return 3 } 33 if bytes_eq(nxhf_verdict_name(NXHF_NOT_FOUND), "NOT_FOUND" as *u8, 9) != 1 { return 4 } 34 35 // ---- tolower / eq_ci ---- 36 if nxhf_tolower(0x41) != 0x61 { return 10 } // A -> a 37 if nxhf_tolower(0x5a) != 0x7a { return 11 } // Z -> z 38 if nxhf_tolower(0x61) != 0x61 { return 12 } // a -> a 39 if nxhf_tolower(0x30) != 0x30 { return 13 } // 0 -> 0 40 41 if nxhf_eq_ci("Content-Type" as *u8, "content-type" as *u8, 12) != 1 { return 20 } 42 if nxhf_eq_ci("X-Foo" as *u8, "X-FOO" as *u8, 5) != 1 { return 21 } 43 if nxhf_eq_ci("abc" as *u8, "abd" as *u8, 3) != 0 { return 22 } 44 45 // ---- Build canonical response header block ---- 46 let buf: *u8 = sys_mmap(1024) 47 var o: i64 = 0 48 o = emit(buf, o, "HTTP/1.1 200 OK\r\n" as *u8) 49 o = emit(buf, o, "Content-Type: application/json\r\n" as *u8) 50 o = emit(buf, o, "Replay-Nonce: oFvnlFP1wIhRlYS2jTaXbA\r\n" as *u8) 51 o = emit(buf, o, "Content-Length: 42\r\n" as *u8) 52 o = emit(buf, o, "Server: nishi-http/0.1\r\n" as *u8) 53 o = emit(buf, o, "\r\n" as *u8) 54 55 // ---- Find Content-Type ---- 56 let voff: *i64 = sys_mmap(8) as *i64 57 let vlen: *i64 = sys_mmap(8) as *i64 58 let rc1: i64 = nx_http_header_find(buf, o, "Content-Type" as *u8, 12, 59 voff, vlen) 60 if rc1 != NXHF_FOUND { return 30 } 61 if vlen[0] != 16 { return 31 } 62 let v1_ptr: *u8 = ((buf as i64) + voff[0]) as *u8 63 if bytes_eq(v1_ptr, "application/json" as *u8, 16) != 1 { return 32 } 64 65 // ---- Case-insensitive: find "content-type" (lowercase) ---- 66 let rc2: i64 = nx_http_header_find(buf, o, "content-type" as *u8, 12, 67 voff, vlen) 68 if rc2 != NXHF_FOUND { return 40 } 69 if vlen[0] != 16 { return 41 } 70 71 // ---- Find Replay-Nonce (the ACME use case) ---- 72 let rc3: i64 = nx_http_header_find(buf, o, "Replay-Nonce" as *u8, 12, 73 voff, vlen) 74 if rc3 != NXHF_FOUND { return 50 } 75 if vlen[0] != 22 { return 51 } 76 let v3_ptr: *u8 = ((buf as i64) + voff[0]) as *u8 77 if bytes_eq(v3_ptr, "oFvnlFP1wIhRlYS2jTaXbA" as *u8, 22) != 1 { return 52 } 78 79 // ---- Case-insensitive: find "REPLAY-NONCE" ---- 80 let rc4: i64 = nx_http_header_find(buf, o, "REPLAY-NONCE" as *u8, 12, 81 voff, vlen) 82 if rc4 != NXHF_FOUND { return 60 } 83 if vlen[0] != 22 { return 61 } 84 85 // ---- NOT_FOUND ---- 86 let rc5: i64 = nx_http_header_find(buf, o, "Set-Cookie" as *u8, 10, 87 voff, vlen) 88 if rc5 != NXHF_NOT_FOUND { return 70 } 89 90 // ---- Content-Length value ---- 91 let rc6: i64 = nx_http_header_find(buf, o, "Content-Length" as *u8, 14, 92 voff, vlen) 93 if rc6 != NXHF_FOUND { return 80 } 94 if vlen[0] != 2 { return 81 } 95 let v6_ptr: *u8 = ((buf as i64) + voff[0]) as *u8 96 if v6_ptr[0] != 0x34 as u8 { return 82 } // '4' 97 if v6_ptr[1] != 0x32 as u8 { return 83 } // '2' 98 99 // ---- Server (single token, no spaces) ---- 100 let rc7: i64 = nx_http_header_find(buf, o, "Server" as *u8, 6, 101 voff, vlen) 102 if rc7 != NXHF_FOUND { return 90 } 103 if vlen[0] != 14 { return 91 } 104 let v7_ptr: *u8 = ((buf as i64) + voff[0]) as *u8 105 if bytes_eq(v7_ptr, "nishi-http/0.1" as *u8, 14) != 1 { return 92 } 106 107 // ---- LF-only line endings (RFC 7230 ยง3.5 tolerance) ---- 108 let buf2: *u8 = sys_mmap(256) 109 var o2: i64 = 0 110 o2 = emit(buf2, o2, "HTTP/1.1 200 OK\n" as *u8) 111 o2 = emit(buf2, o2, "X-Token: abc123\n" as *u8) 112 o2 = emit(buf2, o2, "\n" as *u8) 113 let rc8: i64 = nx_http_header_find(buf2, o2, "X-Token" as *u8, 7, 114 voff, vlen) 115 if rc8 != NXHF_FOUND { return 100 } 116 if vlen[0] != 6 { return 101 } 117 let v8_ptr: *u8 = ((buf2 as i64) + voff[0]) as *u8 118 if bytes_eq(v8_ptr, "abc123" as *u8, 6) != 1 { return 102 } 119 120 // ---- Whitespace trim around value ---- 121 let buf3: *u8 = sys_mmap(256) 122 var o3: i64 = 0 123 o3 = emit(buf3, o3, "HTTP/1.1 200 OK\r\n" as *u8) 124 o3 = emit(buf3, o3, "X-Pad: spaced-value \r\n" as *u8) 125 o3 = emit(buf3, o3, "\r\n" as *u8) 126 let rc9: i64 = nx_http_header_find(buf3, o3, "X-Pad" as *u8, 5, 127 voff, vlen) 128 if rc9 != NXHF_FOUND { return 110 } 129 if vlen[0] != 12 { return 111 } 130 let v9_ptr: *u8 = ((buf3 as i64) + voff[0]) as *u8 131 if bytes_eq(v9_ptr, "spaced-value" as *u8, 12) != 1 { return 112 } 132 133 // ---- BAD_ARG paths ---- 134 if nx_http_header_find(0 as *u8, 100, "X" as *u8, 1, voff, vlen) != NXHF_BAD_ARG { return 120 } 135 if nx_http_header_find(buf, 0, "X" as *u8, 1, voff, vlen) != NXHF_BAD_ARG { return 121 } 136 if nx_http_header_find(buf, 100, 0 as *u8, 1, voff, vlen) != NXHF_BAD_ARG { return 122 } 137 if nx_http_header_find(buf, 100, "X" as *u8, 0, voff, vlen) != NXHF_BAD_ARG { return 123 } 138 if nx_http_header_find(buf, 100, "X" as *u8, 1, 0 as *i64, vlen) != NXHF_BAD_ARG { return 124 } 139 if nx_http_header_find(buf, 100, "X" as *u8, 1, voff, 0 as *i64) != NXHF_BAD_ARG { return 125 } 140 141 return 0 142}