nx_lib_httpd.nx source
↩ module page · 107 lines · 4500 B
1// nx_lib_httpd.nx -- sovereign HTTP DAEMON for the nishi-library read API.
2// Serves the READ PATH over the wire straight from nx_lib_store, RETIRING the
3// Python serve.py endpoints + its SQLite. No python, no 3rd-party HTTP stack,
4// no shell: raw sovereign sockets (nx_syscalls, pulled via nx_lib_serve -- so
5// we do NOT import nx_syscalls_x86_64.nx = no sys_* double-emit) + the pure
6// router nx_lib_http.
7// GET /api/works -> JSON array of work_hks
8// GET /api/work/<hk> -> JSON work record (200) or 404
9// license_tier: ORIGINAL | genealogy_id: nishi_library_sovereign_httpd_2026_06_30
10import "nx_lib_http.nx"
11
12const LHD_AF_INET: i64 = 2
13const LHD_SOCK_STREAM: i64 = 1
14const LHD_SOL_SOCKET: i64 = 1
15const LHD_SO_REUSEADDR: i64 = 2
16const LHD_PORT: i64 = 8095
17const LHD_BACKLOG: i64 = 128
18const LHD_BUDGET: i64 = 1000000 // JPL-rule-2 bounded accept loop
19
20func lhd_write_all(fd: i64, buf: *u8, n: i64) -> i64 {
21 var off: i64 = 0
22 while off < n {
23 let p: *u8 = ((buf as i64) + off) as *u8
24 let w: i64 = sys_write(fd, p, n - off)
25 if w <= 0 { return 0 }
26 off = off + w
27 }
28 return 0
29}
30
31// read one request off cfd, route via nx_lib_http, write the response.
32// GET -> read routes; POST /api/ingest -> write route.
33func lhd_handle(cfd: i64) -> i64 {
34 let req: *u8 = sys_mmap(131072)
35 let n: i64 = sys_read(cfd, req, 131072)
36 if n < 5 { return 0 }
37 let out: *u8 = sys_mmap(1200000)
38 let m0: i64 = req[0] as i64
39 if m0 == 71 { // 'G' GET ("GET " -> path at 4)
40 let path: *u8 = ((req as i64) + 4) as *u8
41 var pe: i64 = 4
42 var path_end: i64 = 0 - 1
43 while pe < n { if path_end < 0 { if (req[pe] as i64) == 32 { path_end = pe } } pe = pe + 1 }
44 if path_end < 0 { path_end = n }
45 let rn: i64 = lhd_response(path, path_end - 4, out)
46 lhd_write_all(cfd, out, rn)
47 } else { if m0 == 80 { // 'P' POST ("POST " -> path at 5)
48 let path: *u8 = ((req as i64) + 5) as *u8
49 var pe: i64 = 5
50 var path_end: i64 = 0 - 1
51 while pe < n { if path_end < 0 { if (req[pe] as i64) == 32 { path_end = pe } } pe = pe + 1 }
52 if path_end < 0 { path_end = n }
53 let path_n: i64 = path_end - 5
54 // body starts after CRLF CRLF
55 var bs: i64 = 0 - 1
56 var bi: i64 = 0
57 while bi + 3 < n {
58 if bs < 0 { if req[bi] == 13 as u8 { if req[bi+1] == 10 as u8 { if req[bi+2] == 13 as u8 { if req[bi+3] == 10 as u8 { bs = bi + 4 } } } } }
59 bi = bi + 1
60 }
61 if lhd_starts(path, path_n, "/api/ingest" as *u8) == 1 {
62 var bptr: *u8 = ("" as *u8)
63 var blen: i64 = 0
64 if bs >= 0 { bptr = ((req as i64) + bs) as *u8; blen = n - bs }
65 let rn: i64 = lhd_ingest_response(bptr, blen, out)
66 lhd_write_all(cfd, out, rn)
67 } else {
68 let rn: i64 = lhd_response("/nf" as *u8, 3, out)
69 lhd_write_all(cfd, out, rn)
70 }
71 } }
72 return 0
73}
74
75// sockaddr_in (16 bytes) for 0.0.0.0:<port>, port in network (big-endian) order.
76func lhd_sockaddr(addr: *u8, port: i64) -> i64 {
77 addr[0] = 2 as u8 // AF_INET family low byte
78 addr[1] = 0 as u8
79 addr[2] = ((port / 256) & 255) as u8 // port hi (network order)
80 addr[3] = (port & 255) as u8 // port lo
81 var i: i64 = 4
82 while i < 16 { addr[i] = 0 as u8; i = i + 1 } // INADDR_ANY + zero pad
83 return 0
84}
85
86func main() -> i64 {
87 let fd: i64 = sys_socket(LHD_AF_INET, LHD_SOCK_STREAM, 0)
88 if fd < 0 { return 10 }
89 let one: *u8 = sys_mmap(4)
90 one[0] = 1 as u8; one[1] = 0 as u8; one[2] = 0 as u8; one[3] = 0 as u8
91 sys_setsockopt(fd, LHD_SOL_SOCKET, LHD_SO_REUSEADDR, one, 4)
92 let addr: *u8 = sys_mmap(16)
93 lhd_sockaddr(addr, LHD_PORT)
94 if sys_bind(fd, addr, 16) < 0 { return 11 }
95 if sys_listen(fd, LHD_BACKLOG) < 0 { return 12 }
96 nx_lib_index_build() // build the persisted inverted index once at startup (O(1) /api/search)
97 let banner: *u8 = "nx_lib_httpd: sovereign library API on 0.0.0.0:8095 (reads nx_lib_store; no python/sqlite/3rd-party)\n" as *u8
98 sys_write(1, banner, ls_strlen(banner))
99 var served: i64 = 0
100 while served < LHD_BUDGET {
101 let cfd: i64 = sys_accept(fd)
102 if cfd >= 0 { lhd_handle(cfd); sys_close(cfd) }
103 served = served + 1
104 }
105 sys_close(fd)
106 return 0
107}