code wiki / _hdl_build / nx_route.nx
nx_route.nx source
↩ module page · 51 lines · 4056 B
1// nx_route.nx -- the SOVEREIGN S-CLASS ROUTING ENGINE: one declarative pure function every delivery flows through,
2// replacing per-path if-chains. URL path + a resource manifest -> a routing DECISION. S-class properties, uniform
3// for ALL resources (qualitative: clean+canonical+safe; quantitative: one engine, every path handled the same):
4// * CLEAN extensionless URLs: /vn -> serves vn.html ; /foo -> foo/index.html ; exact assets (/x.png,/x.css) served
5// * ONE CANONICAL url: /vn.html -> 301 /vn ; /vn/ -> 301 /vn (trailing slash) -> no more "/vn vs /vn.html" mess
6// * TRAVERSAL-SAFE: any ".." -> 400 (never serves outside the docroot)
7// * deterministic + pure (path+manifest in, decision out) -> fully gateable with zero live-daemon risk.
8// codes: 0=SERVE(out=file) 1=REDIRECT-301(out=location) 2=NOT-FOUND 3=BAD-REQUEST(traversal). license_tier: ORIGINAL
9import "nx_syscalls.nx"
10const K_MAGIC_1024: i64 = 1024
11
12func r_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
13func r_cpy(dst: *u8, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[i] = s[i]; i = i + 1 } dst[i] = 0 as u8; return i }
14func r_cpyn(dst: *u8, s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { dst[i] = s[i]; i = i + 1 } dst[i] = 0 as u8; return i }
15func r_ends(s: *u8, suf: *u8) -> i64 { let ls: i64 = r_len(s); let lf: i64 = r_len(suf); if lf > ls { return 0 } var i: i64 = 0; while i < lf { if s[ls-lf+i] != suf[i] { return 0 } i = i + 1 } return 1 }
16func r_dotdot(s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { if s[i] == (46 as u8) { if s[i+1] == (46 as u8) { return 1 } } i = i + 1 } return 0 }
17// substring search
18func r_find(hay: *u8, needle: *u8) -> i64 {
19 let nl: i64 = r_len(needle); if nl == 0 { return 1 }
20 var i: i64 = 0
21 while hay[i] != (0 as u8) { var j: i64 = 0; var ok: i64 = 1; while j < nl { if hay[i+j] != needle[j] { ok = 0; j = nl } else { j = j + 1 } } if ok == 1 { return 1 } i = i + 1 }
22 return 0
23}
24// is `entry` a whole line in manifest? (manifest is newline-bounded: starts+ends with '\n')
25func r_mem(manifest: *u8, entry: *u8) -> i64 {
26 let nd: *u8 = sys_mmap(K_MAGIC_1024); var o: i64 = 0; nd[o] = 10 as u8; o = o + 1
27 var i: i64 = 0; while entry[i] != (0 as u8) { nd[o] = entry[i]; o = o + 1; i = i + 1 } nd[o] = 10 as u8; o = o + 1; nd[o] = 0 as u8
28 return r_find(manifest, nd)
29}
30
31// THE ENGINE. path = request path (no query). manifest = "\n/a.html\n/b/index.html\n..." . out = result string.
32func route(path: *u8, manifest: *u8, out: *u8) -> i64 {
33 if r_dotdot(path) == 1 { r_cpy(out, "/" as *u8); return 3 } // traversal -> bad request
34 let n: i64 = r_len(path)
35 if n == 0 { r_cpy(out, "/" as *u8); return 1 } // empty -> /
36 // canonical: strip trailing slash (except root)
37 if n > 1 { if path[n-1] == (47 as u8) { r_cpyn(out, path, n-1); return 1 } }
38 // canonical: .html -> extensionless
39 if r_ends(path, ".html" as *u8) == 1 { r_cpyn(out, path, n-5); return 1 }
40 // resolve to a served file
41 if n == 1 { // "/"
42 if r_mem(manifest, "/index.html" as *u8) == 1 { r_cpy(out, "/index.html" as *u8); return 0 }
43 return 2
44 }
45 let c1: *u8 = sys_mmap(K_MAGIC_1024); let l1: i64 = r_cpy(c1, path); c1[l1] = 46 as u8; c1[l1+1]=104 as u8; c1[l1+2]=116 as u8; c1[l1+3]=109 as u8; c1[l1+4]=108 as u8; c1[l1+5]=0 as u8 // path + ".html"
46 if r_mem(manifest, c1) == 1 { r_cpy(out, c1); return 0 }
47 let c2: *u8 = sys_mmap(K_MAGIC_1024); var l2: i64 = r_cpy(c2, path); c2[l2]=47 as u8; l2 = l2 + 1; var k: i64 = 0; let idx: *u8 = "index.html" as *u8; while idx[k] != (0 as u8) { c2[l2]=idx[k]; l2=l2+1; k=k+1 } c2[l2]=0 as u8 // path + "/index.html"
48 if r_mem(manifest, c2) == 1 { r_cpy(out, c2); return 0 }
49 if r_mem(manifest, path) == 1 { r_cpy(out, path); return 0 } // exact asset (.png/.css/...)
50 return 2 // not found
51}