code wiki / _hdl_build / nx_host_router_gate.nx
nx_host_router_gate.nx source
↩ module page · 98 lines · 5916 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"
8
9func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func 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 }
11func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
12
13func mkfile(p: *u8, c: *u8) -> i64 {
14 let fd: i64 = sys_openat_wr(p, 420)
15 if fd < 0 { w(" CANNOT CREATE "); w(p); w("\n" as *u8); return 1 }
16 sys_write(fd, c, slen(c)); sys_close(fd); return 0
17}
18func mkreq(buf: *u8, path: *u8) -> i64 {
19 var j: i64=0; var k: i64=0
20 let a: *u8="GET " as *u8; while a[k]!=(0 as u8){buf[j]=a[k];j=j+1;k=k+1}
21 k=0; while path[k]!=(0 as u8){buf[j]=path[k];j=j+1;k=k+1}
22 let b: *u8=" HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8
23 k=0; while b[k]!=(0 as u8){buf[j]=b[k];j=j+1;k=k+1}
24 return j
25}
26// substring search in h[0..n)
27func hsearch(h: *u8, n: i64, ndl: *u8) -> i64 {
28 let nl: i64 = slen(ndl); if nl==0 { return 0 }
29 var i: i64=0
30 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 }
31 return 0
32}
33
34// run one request; check verdict + (optional) marker substring present in the response bytes.
35func chk(cfg: *u8, cfgn: i64, path: *u8, expv: i64, marker: *u8) -> i64 {
36 let req: *u8 = sys_mmap(4096); let reqn: i64 = mkreq(req, path)
37 let out: *u8 = sys_mmap(65536); let out_n: *i64 = (sys_mmap(8)) as *i64
38 let v: i64 = hr_serve3(cfg, cfgn, req, reqn, out, 65536, out_n)
39 var ok: i64 = 1
40 if v != expv { ok = 0 }
41 if (marker as i64) != 0 { if hsearch(out, out_n[0], marker) == 0 { ok = 0 } }
42 w(" "); w(path); w(" -> v="); wn(v); w(" n="); wn(out_n[0])
43 if ok==1 { w(" ok\n" as *u8) } else { w(" FAIL(exp v="); wn(expv); w(")\n" as *u8) }
44 return ok
45}
46
47func main(argc: i64, argv: *i64) -> i64 {
48 w("=== nx_host_router_gate -- hr_serve3 S-class routing on a live docroot ===\n" as *u8)
49 sys_mkdir("/tmp/hrt" as *u8, 0x1ed); sys_mkdir("/tmp/hrt/blog" as *u8, 0x1ed); sys_mkdir("/tmp/hrt/games" as *u8, 0x1ed)
50 mkfile("/tmp/hrt/index.html" as *u8, "<!doctype html><h1>HOMEPAGE-ROOT</h1>" as *u8)
51 mkfile("/tmp/hrt/style.css" as *u8, "body{color:red}" as *u8)
52 mkfile("/tmp/hrt/blog/index.html" as *u8, "<!doctype html><h1>BLOG-INDEX</h1>" as *u8)
53 mkfile("/tmp/hrt/vn.html" as *u8, "<!doctype html><h1>VN-FLATFILE</h1>" as *u8)
54 mkfile("/tmp/hrt/games/index.html" as *u8, "<!doctype html><h1>GAMES-HUB-DIR</h1>" as *u8)
55 mkfile("/tmp/hrt/games.html" as *u8, "<!doctype html><h1>GAMES-STALE-FLAT</h1>" as *u8)
56 let cfg: *u8 = "* /tmp/hrt\n" as *u8
57 let cfgn: i64 = slen(cfg)
58 var pass: i64 = 0; var tot: i64 = 0
59
60 w(" T1 clean URLs serve (dir + flat + root):\n" as *u8)
61 var a: i64 = 1
62 if chk(cfg,cfgn,"/blog" as *u8, HR_S2_OK, "BLOG-INDEX" as *u8)==0 { a=0 }
63 if chk(cfg,cfgn,"/vn" as *u8, HR_S2_OK, "VN-FLATFILE" as *u8)==0 { a=0 }
64 if chk(cfg,cfgn,"/" as *u8, HR_S2_OK, "HOMEPAGE-ROOT" as *u8)==0 { a=0 }
65 tot=tot+1; if a==1 { pass=pass+1; w(" PASS T1\n" as *u8) } else { w(" FAIL T1\n" as *u8) }
66
67 w(" T2 ONE canonical URL via REAL 301 (.html / trailing-slash / index.html):\n" as *u8)
68 var b: i64 = 1
69 if chk(cfg,cfgn,"/vn.html" as *u8, HR_S2_REDIR, "Location: /vn\r" as *u8)==0 { b=0 }
70 if chk(cfg,cfgn,"/blog/" as *u8, HR_S2_REDIR, "Location: /blog\r" as *u8)==0 { b=0 }
71 if chk(cfg,cfgn,"/index.html" as *u8, HR_S2_REDIR, "Location: /\r" as *u8)==0 { b=0 }
72 if chk(cfg,cfgn,"/blog/index.html" as *u8, HR_S2_REDIR, "Location: /blog\r" as *u8)==0 { b=0 }
73 if chk(cfg,cfgn,"/vn.html" as *u8, HR_S2_REDIR, "301 Moved" as *u8)==0 { b=0 }
74 tot=tot+1; if b==1 { pass=pass+1; w(" PASS T2\n" as *u8) } else { w(" FAIL T2\n" as *u8) }
75
76 w(" T3 assets served exact (MIME + bytes):\n" as *u8)
77 var c: i64 = 1
78 if chk(cfg,cfgn,"/style.css" as *u8, HR_S2_OK, "body{color:red}" as *u8)==0 { c=0 }
79 if chk(cfg,cfgn,"/style.css" as *u8, HR_S2_OK, "text/css" as *u8)==0 { c=0 }
80 tot=tot+1; if c==1 { pass=pass+1; w(" PASS T3\n" as *u8) } else { w(" FAIL T3\n" as *u8) }
81
82 w(" T4 safe: traversal 400, miss falls through, NO 301-to-404 (neg-controls):\n" as *u8)
83 var d: i64 = 1
84 if chk(cfg,cfgn,"/a/../b" as *u8, HR_S2_BAD, "400" as *u8)==0 { d=0 }
85 if chk(cfg,cfgn,"/nope" as *u8, HR_S2_MISS, 0 as *u8)==0 { d=0 }
86 if chk(cfg,cfgn,"/ghost.html" as *u8, HR_S2_MISS, 0 as *u8)==0 { d=0 }
87 tot=tot+1; if d==1 { pass=pass+1; w(" PASS T4\n" as *u8) } else { w(" FAIL T4\n" as *u8) }
88
89 w(" T5 NO REGRESSION: dir-index keeps precedence (hub not shadowed by stale flat) + flat 301s to it:\n" as *u8)
90 var e: i64 = 1
91 if chk(cfg,cfgn,"/games" as *u8, HR_S2_OK, "GAMES-HUB-DIR" as *u8)==0 { e=0 }
92 if chk(cfg,cfgn,"/games.html" as *u8, HR_S2_REDIR, "Location: /games\r" as *u8)==0 { e=0 }
93 tot=tot+1; if e==1 { pass=pass+1; w(" PASS T5\n" as *u8) } else { w(" FAIL T5\n" as *u8) }
94
95 w("nx_host_router_gate pass="); wn(pass); w("/"); wn(tot)
96 if pass==tot { w(" verdict=GREEN (S-class routing LIVE-handler: clean + canonical-301 + safe + no-regression)\n" as *u8); sys_exit(0); return 0 }
97 w(" verdict=RED\n" as *u8); sys_exit(1); return 1
98}