code wiki / _hdl_build / nx_host_router_gate.nx

nx_host_router_gate.nx source

↩ module page · 106 lines · 6297 B

1// nx_host_router_gate.nx -- proves hr_serve3 (S-class routing) end-to-end against a REAL temp docroot. 2// Routing is a property of the HOST: ONE resolver gives clean URLs (dir AND flat layouts) + real 301s to 3// ONE canonical URL, while (a) keeping dir-index PRECEDENCE so an existing hub is never shadowed, and 4// (b) never 301-ing into a 404. This is the live-daemon counterpart of nx_route_gate (pure logic, 5/5). 5// license_tier: ORIGINAL expect_exit: 0 6import "nx_host_router.nx" 7import "nx_syscalls.nx" 8import "nx_gate_verdict.nx" 9 10func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func wn(v: i64) -> i64 { var m: i64=v; if m<0{w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 } 12func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 13 14func mkfile(p: *u8, c: *u8) -> i64 { 15 let fd: i64 = sys_openat_wr(p, 420) 16 if fd < 0 { w(" CANNOT CREATE "); w(p); w("\n" as *u8); return 1 } 17 sys_write(fd, c, slen(c)); sys_close(fd); return 0 18} 19func mkreq(buf: *u8, path: *u8) -> i64 { 20 var j: i64=0; var k: i64=0 21 let a: *u8="GET " as *u8; while a[k]!=(0 as u8){buf[j]=a[k];j=j+1;k=k+1} 22 k=0; while path[k]!=(0 as u8){buf[j]=path[k];j=j+1;k=k+1} 23 let b: *u8=" HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8 24 k=0; while b[k]!=(0 as u8){buf[j]=b[k];j=j+1;k=k+1} 25 return j 26} 27// substring search in h[0..n) 28func hsearch(h: *u8, n: i64, ndl: *u8) -> i64 { 29 let nl: i64 = slen(ndl); if nl==0 { return 0 } 30 var i: i64=0 31 while i+nl<=n { var j: i64=0; var ok: i64=1; while j<nl{ if h[i+j]!=ndl[j]{ok=0;j=nl} else {j=j+1} } if ok==1{return 1} i=i+1 } 32 return 0 33} 34 35// run one request; check verdict + (optional) marker substring present in the response bytes. 36func chk(cfg: *u8, cfgn: i64, path: *u8, expv: i64, marker: *u8) -> i64 { 37 let req: *u8 = sys_mmap(4096); let reqn: i64 = mkreq(req, path) 38 let out: *u8 = sys_mmap(65536); let out_n: *i64 = (sys_mmap(8)) as *i64 39 let v: i64 = hr_serve3(cfg, cfgn, req, reqn, out, 65536, out_n) 40 var ok: i64 = 1 41 if v != expv { ok = 0 } 42 if (marker as i64) != 0 { if hsearch(out, out_n[0], marker) == 0 { ok = 0 } } 43 w(" "); w(path); w(" -> v="); wn(v); w(" n="); wn(out_n[0]) 44 if ok==1 { w(" ok\n" as *u8) } else { w(" FAIL(exp v="); wn(expv); w(")\n" as *u8) } 45 return ok 46} 47 48func main(argc: i64, argv: *i64) -> i64 { 49 w("=== nx_host_router_gate -- hr_serve3 S-class routing on a live docroot ===\n" as *u8) 50 sys_mkdir("/tmp/hrt" as *u8, 0x1ed); sys_mkdir("/tmp/hrt/blog" as *u8, 0x1ed); sys_mkdir("/tmp/hrt/games" as *u8, 0x1ed) 51 mkfile("/tmp/hrt/index.html" as *u8, "<!doctype html><h1>HOMEPAGE-ROOT</h1>" as *u8) 52 mkfile("/tmp/hrt/style.css" as *u8, "body{color:red}" as *u8) 53 mkfile("/tmp/hrt/blog/index.html" as *u8, "<!doctype html><h1>BLOG-INDEX</h1>" as *u8) 54 mkfile("/tmp/hrt/vn.html" as *u8, "<!doctype html><h1>VN-FLATFILE</h1>" as *u8) 55 mkfile("/tmp/hrt/games/index.html" as *u8, "<!doctype html><h1>GAMES-HUB-DIR</h1>" as *u8) 56 mkfile("/tmp/hrt/games.html" as *u8, "<!doctype html><h1>GAMES-STALE-FLAT</h1>" as *u8) 57 let cfg: *u8 = "* /tmp/hrt\n" as *u8 58 let cfgn: i64 = slen(cfg) 59 var pass: i64 = 0; var tot: i64 = 0 60 61 w(" T1 clean URLs serve (dir + flat + root):\n" as *u8) 62 var a: i64 = 1 63 if chk(cfg,cfgn,"/blog" as *u8, HR_S2_OK, "BLOG-INDEX" as *u8)==0 { a=0 } 64 if chk(cfg,cfgn,"/vn" as *u8, HR_S2_OK, "VN-FLATFILE" as *u8)==0 { a=0 } 65 if chk(cfg,cfgn,"/" as *u8, HR_S2_OK, "HOMEPAGE-ROOT" as *u8)==0 { a=0 } 66 tot=tot+1; if a==1 { pass=pass+1; w(" PASS T1\n" as *u8) } else { w(" FAIL T1\n" as *u8) } 67 68 w(" T2 ONE canonical URL via REAL 301 (.html / trailing-slash / index.html):\n" as *u8) 69 var b: i64 = 1 70 if chk(cfg,cfgn,"/vn.html" as *u8, HR_S2_REDIR, "Location: /vn\r" as *u8)==0 { b=0 } 71 if chk(cfg,cfgn,"/blog/" as *u8, HR_S2_REDIR, "Location: /blog\r" as *u8)==0 { b=0 } 72 if chk(cfg,cfgn,"/index.html" as *u8, HR_S2_REDIR, "Location: /\r" as *u8)==0 { b=0 } 73 if chk(cfg,cfgn,"/blog/index.html" as *u8, HR_S2_REDIR, "Location: /blog\r" as *u8)==0 { b=0 } 74 if chk(cfg,cfgn,"/vn.html" as *u8, HR_S2_REDIR, "301 Moved" as *u8)==0 { b=0 } 75 tot=tot+1; if b==1 { pass=pass+1; w(" PASS T2\n" as *u8) } else { w(" FAIL T2\n" as *u8) } 76 77 w(" T3 assets served exact (MIME + bytes):\n" as *u8) 78 var c: i64 = 1 79 if chk(cfg,cfgn,"/style.css" as *u8, HR_S2_OK, "body{color:red}" as *u8)==0 { c=0 } 80 if chk(cfg,cfgn,"/style.css" as *u8, HR_S2_OK, "text/css" as *u8)==0 { c=0 } 81 tot=tot+1; if c==1 { pass=pass+1; w(" PASS T3\n" as *u8) } else { w(" FAIL T3\n" as *u8) } 82 83 w(" T4 safe: traversal 400, miss falls through, NO 301-to-404 (neg-controls):\n" as *u8) 84 var d: i64 = 1 85 if chk(cfg,cfgn,"/a/../b" as *u8, HR_S2_BAD, "400" as *u8)==0 { d=0 } 86 if chk(cfg,cfgn,"/nope" as *u8, HR_S2_MISS, 0 as *u8)==0 { d=0 } 87 if chk(cfg,cfgn,"/ghost.html" as *u8, HR_S2_MISS, 0 as *u8)==0 { d=0 } 88 tot=tot+1; if d==1 { pass=pass+1; w(" PASS T4\n" as *u8) } else { w(" FAIL T4\n" as *u8) } 89 90 w(" T5 NO REGRESSION: dir-index keeps precedence (hub not shadowed by stale flat) + flat 301s to it:\n" as *u8) 91 var e: i64 = 1 92 if chk(cfg,cfgn,"/games" as *u8, HR_S2_OK, "GAMES-HUB-DIR" as *u8)==0 { e=0 } 93 if chk(cfg,cfgn,"/games.html" as *u8, HR_S2_REDIR, "Location: /games\r" as *u8)==0 { e=0 } 94 tot=tot+1; if e==1 { pass=pass+1; w(" PASS T5\n" as *u8) } else { w(" FAIL T5\n" as *u8) } 95 96 w("nx_host_router_gate pass="); wn(pass); w("/"); wn(tot) 97 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 98 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 99 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 100 let ctr__dry: *i64 = gv_ctr() 101 ctr__dry[0] = pass 102 ctr__dry[1] = tot 103 let rc__dry: i64 = gv_verdict("HOST-ROUTER-GATE" as *u8, ctr__dry, "S-class routing LIVE-handler: clean + canonical-301 + safe + no-regression)" as *u8) 104 sys_exit(rc__dry) 105 return rc__dry 106}