code wiki / _hdl_build / nx_manga_search.nx
nx_manga_search.nx source
↩ module page · 371 lines · 21130 B
1// nx_manga_search.nx -- the SOURCE BROWSER backend (operator 2026-07-04: "i want the sites to choose to download or
2// translate like i could in media manager"). On-site SEARCH for the sources we support, served to the /library/manga
3// page so the operator picks a source, searches it, and taps a result to download -- the Mihon/media-manager model.
4// /api/msearch?src=mangadex&q=.. -> MangaDex API (/manga?title=) -> [{t,id,thumb,kind:series}]
5// /api/msearch?src=nhentai&q=.. -> nhentai /search/ HTML (its old API is 403'd) -> [{t,url,thumb,kind:gallery}]
6// /api/mfeed?id=<mangaId> -> MangaDex chapter feed -> [{ch,t,id}] (series -> chapters second level)
7// /api/thumb?u=<enc url> -> PROXY a cover through our sovereign Chrome client (beats Cloudflare/hotlink),
8// so thumbnails ALWAYS render in the browser regardless of referer checks.
9// All live fetches via nx_https_fetch_follow_chrome (Chrome-JA3 + RSA-PSS + honest UA). Parsers match REAL shapes
10// captured with the sovereign client. Reuses na_* (nx_manga_sites) + zs_* (nx_reader_zoomserve). license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_x509_trust_store.nx"
13import "nx_trust_store_load_from_certdata.nx"
14import "nx_https_fetch_follow.nx"
15import "nx_manga_sites.nx" // na_find_from / na_apps
16import "nx_reader_zoomserve.nx" // zs_emit / zs_qval / zs_apps / zs_slen
17const MSS_MAGIC_4194304: i64 = 4194304
18const MSS_MAGIC_1536: i64 = 1536
19const MSS_MAGIC_2048: i64 = 2048
20const MSS_MAGIC_1024: i64 = 1024
21
22const MSS_FETCH_CAP: i64 = 2097152 // 2MB (mangadex/nhentai search pages ~40KB; covers up to ~1MB)
23const MSS_OUT_CAP: i64 = 131072
24
25func mss_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
26
27// percent-encode a query into out (alnum + -_.~ pass; space + others -> %XX). returns len.
28func mss_qenc(src: *u8, n: i64, out: *u8) -> i64 {
29 let hx: *u8 = "0123456789ABCDEF" as *u8
30 var o: i64 = 0; var i: i64 = 0
31 while i < n {
32 let c: i64 = src[i] as i64
33 var safe: i64 = 0
34 if c >= 48 { if c <= 57 { safe = 1 } }
35 if c >= 65 { if c <= 90 { safe = 1 } }
36 if c >= 97 { if c <= 122 { safe = 1 } }
37 if c == 45 { safe = 1 } if c == 95 { safe = 1 } if c == 46 { safe = 1 } if c == 126 { safe = 1 }
38 if safe == 1 { out[o] = c as u8; o = o + 1 }
39 else { out[o] = 37 as u8; out[o+1] = hx[(c>>4)&0xf]; out[o+2] = hx[c&0xf]; o = o + 3 }
40 i = i + 1
41 }
42 out[o] = 0 as u8
43 return o
44}
45
46// starts-with at position: does buf[pos..] begin with the NUL-term literal `lit`?
47func mss_at(buf: *u8, n: i64, pos: i64, lit: *u8) -> i64 {
48 var j: i64 = 0
49 while lit[j] != (0 as u8) { if pos + j >= n { return 0 } if buf[pos+j] != lit[j] { return 0 } j = j + 1 }
50 return 1
51}
52
53// copy an already-JSON-escaped string value verbatim from src[from..] into dst[o..] until the UNescaped '"'.
54// returns new o; sets endp[0] to the index of that closing quote. (source is valid JSON -> its \" \\ \u pass through.)
55func mss_cpjval(dst: *u8, o: i64, src: *u8, from: i64, n: i64, cap: i64, endp: *i64) -> i64 {
56 var i: i64 = from
57 while i < n {
58 let c: i64 = src[i] as i64
59 if c == 92 { if i + 1 < n { if o < cap - 2 { dst[o] = src[i]; dst[o+1] = src[i+1]; o = o + 2 } i = i + 2 } else { i = n } }
60 else { if c == 34 { endp[0] = i; return o } if o < cap - 1 { dst[o] = src[i]; o = o + 1 } i = i + 1 }
61 }
62 endp[0] = n; return o
63}
64
65// append raw bytes with JSON-string escaping (for HTML-derived titles: escape " and \, drop < 0x20). stops at cap.
66func mss_jesc(dst: *u8, o: i64, src: *u8, from: i64, to: i64, cap: i64) -> i64 {
67 var i: i64 = from
68 while i < to { let c: i64 = src[i] as i64
69 if c == 34 { if o < cap-2 { dst[o]=92 as u8; dst[o+1]=34 as u8; o=o+2 } }
70 else { if c == 92 { if o < cap-2 { dst[o]=92 as u8; dst[o+1]=92 as u8; o=o+2 } }
71 else { if c >= 32 { if o < cap-1 { dst[o]=src[i] as u8; o=o+1 } } } }
72 i = i + 1
73 }
74 return o
75}
76
77// append a proxied-thumb field: ,"thumb":"api/thumb?u=<qenc(realUrl[us..ue))>"
78func mss_thumb_field(dst: *u8, o: i64, real: *u8, us: i64, ue: i64, cap: i64) -> i64 {
79 o = zs_apps(dst, o, ",\"thumb\":\"api/thumb?u=" as *u8)
80 let hx: *u8 = "0123456789ABCDEF" as *u8
81 var i: i64 = us
82 while i < ue { let c: i64 = real[i] as i64
83 var safe: i64 = 0
84 if c >= 48 { if c <= 57 { safe = 1 } } if c >= 65 { if c <= 90 { safe = 1 } } if c >= 97 { if c <= 122 { safe = 1 } }
85 if c == 45 { safe=1 } if c == 95 { safe=1 } if c == 46 { safe=1 } if c == 126 { safe=1 }
86 if safe == 1 { if o < cap-1 { dst[o]=c as u8; o=o+1 } } else { if o < cap-3 { dst[o]=37 as u8; dst[o+1]=hx[(c>>4)&0xf]; dst[o+2]=hx[c&0xf]; o=o+3 } }
87 i = i + 1
88 }
89 dst[o] = 34 as u8; o = o + 1
90 return o
91}
92
93// ---- MangaDex search JSON -> results. entries = `"id":"UUID","type":"manga"`; title = first attributes.title lang;
94// cover fileName from the manga's cover_art relationship -> uploads.mangadex.org/covers/<id>/<file>.256.jpg (proxied).
95func msearch_mangadex(json: *u8, jn: i64, out: *u8, cap: i64) -> i64 {
96 var o: i64 = zs_apps(out, 0, "{\"src\":\"mangadex\",\"kind\":\"series\",\"results\":[" as *u8)
97 var first: i64 = 1
98 let ep: *i64 = sys_mmap(8) as *i64
99 var pos: i64 = 0
100 var guard: i64 = 0
101 while guard < 200 {
102 guard = guard + 1
103 let idp: i64 = na_find_from(json, jn, "\"id\":\"" as *u8, pos)
104 if idp < 0 { guard = 200 } else {
105 let vs: i64 = idp + 6
106 let ve: i64 = na_find_from(json, jn, "\"" as *u8, vs)
107 if ve < 0 { guard = 200 } else {
108 pos = ve + 1
109 if mss_at(json, jn, ve, "\",\"type\":\"manga\"" as *u8) == 1 {
110 // this is a manga entry. bound = next manga
111 let nextm: i64 = na_find_from(json, jn, "\"type\":\"manga\"" as *u8, ve + 10)
112 var bound: i64 = jn; if nextm >= 0 { bound = nextm }
113 // title
114 let tp: i64 = na_find_from(json, jn, "\"title\":{" as *u8, ve)
115 if tp >= 0 { if tp < bound {
116 var a: i64 = tp + 9
117 var r1: i64 = 1; while r1 == 1 { if a >= jn { r1 = 0 } else { if (json[a] as i64)==58 { a=a+1; r1=0 } else { a=a+1 } } }
118 var r2: i64 = 1; while r2 == 1 { if a >= jn { r2 = 0 } else { if (json[a] as i64)==34 { a=a+1; r2=0 } else { a=a+1 } } }
119 if first == 0 { out[o] = 44 as u8; o = o + 1 }
120 first = 0
121 o = zs_apps(out, o, "{\"t\":\"" as *u8)
122 o = mss_cpjval(out, o, json, a, jn, cap, ep)
123 o = zs_apps(out, o, "\",\"id\":\"" as *u8)
124 var c: i64 = vs; while c < ve { if o < cap-1 { out[o]=json[c] as u8; o=o+1 } c=c+1 }
125 out[o] = 34 as u8; o = o + 1
126 // cover (optional): find cover_art then fileName, within [ve, bound)
127 let cvp: i64 = na_find_from(json, jn, "\"type\":\"cover_art\"" as *u8, ve)
128 if cvp >= 0 { if cvp < bound {
129 let fp: i64 = na_find_from(json, jn, "\"fileName\":\"" as *u8, cvp)
130 if fp >= 0 { if fp < bound {
131 let fs: i64 = fp + 12
132 let fe: i64 = na_find_from(json, jn, "\"" as *u8, fs)
133 if fe > fs {
134 // build the real cover url in a temp then proxy it
135 let cu: *u8 = sys_mmap(512); var co: i64 = 0
136 co = zs_apps(cu, co, "https://uploads.mangadex.org/covers/" as *u8)
137 var q: i64 = vs; while q < ve { cu[co]=json[q]; co=co+1; q=q+1 }
138 cu[co]=47 as u8; co=co+1
139 q = fs; while q < fe { cu[co]=json[q]; co=co+1; q=q+1 }
140 co = zs_apps(cu, co, ".256.jpg" as *u8); cu[co]=0 as u8
141 o = mss_thumb_field(out, o, cu, 0, co, cap)
142 }
143 } }
144 } }
145 o = zs_apps(out, o, "}" as *u8)
146 } }
147 }
148 }
149 }
150 }
151 o = zs_apps(out, o, "]}" as *u8); out[o] = 0 as u8
152 return o
153}
154
155// ---- nhentai search HTML -> galleries. card = <a href="/g/ID/" class="cover">..<img alt="TITLE" .. src="THUMB"..>
156func msearch_nhentai(html: *u8, hn: i64, out: *u8, cap: i64) -> i64 {
157 var o: i64 = zs_apps(out, 0, "{\"src\":\"nhentai\",\"kind\":\"gallery\",\"results\":[" as *u8)
158 var first: i64 = 1
159 var pos: i64 = 0
160 var guard: i64 = 0
161 while guard < 400 {
162 guard = guard + 1
163 let gp: i64 = na_find_from(html, hn, "href=\"/g/" as *u8, pos)
164 if gp < 0 { guard = 400 } else {
165 let ds: i64 = gp + 9
166 var de: i64 = ds
167 var rd: i64 = 1
168 while rd == 1 { if de >= hn { rd = 0 } else { let c: i64 = html[de] as i64; if c >= 48 { if c <= 57 { de = de + 1 } else { rd = 0 } } else { rd = 0 } } }
169 pos = gp + 9 // always advance past this href to avoid re-matching
170 // de now points at the first non-digit (should be '/'); require >=1 digit + a trailing '/'
171 if de > ds { if de < hn { if (html[de] as i64) == 47 {
172 // alt title + thumb are within this <a> block (before the next href="/g/)
173 let nextg: i64 = na_find_from(html, hn, "href=\"/g/" as *u8, de)
174 var bound: i64 = hn; if nextg >= 0 { bound = nextg }
175 let ap: i64 = na_find_from(html, hn, "alt=\"" as *u8, de)
176 let sp: i64 = na_find_from(html, hn, "src=\"" as *u8, de)
177 if ap >= 0 { if ap < bound {
178 let as2: i64 = ap + 5
179 let ae: i64 = na_find_from(html, hn, "\"" as *u8, as2)
180 if ae > as2 {
181 if first == 0 { out[o] = 44 as u8; o = o + 1 }
182 first = 0
183 o = zs_apps(out, o, "{\"t\":\"" as *u8)
184 o = mss_jesc(out, o, html, as2, ae, cap)
185 o = zs_apps(out, o, "\",\"url\":\"https://nhentai.net/g/" as *u8)
186 var c: i64 = ds; while c < de { if o < cap-1 { out[o]=html[c] as u8; o=o+1 } c=c+1 }
187 o = zs_apps(out, o, "/\"" as *u8)
188 if sp >= 0 { if sp < bound {
189 let ss: i64 = sp + 5
190 let se: i64 = na_find_from(html, hn, "\"" as *u8, ss)
191 if se > ss { o = mss_thumb_field(out, o, html, ss, se, cap) }
192 } }
193 o = zs_apps(out, o, "}" as *u8)
194 }
195 } }
196 } } }
197 }
198 }
199 o = zs_apps(out, o, "]}" as *u8); out[o] = 0 as u8
200 return o
201}
202
203// ---- MangaDex chapter feed -> [{ch,t,id}]. entries = `"id":"UUID","type":"chapter"`; ch=attributes.chapter.
204func mfeed_mangadex(json: *u8, jn: i64, out: *u8, cap: i64) -> i64 {
205 var o: i64 = zs_apps(out, 0, "{\"kind\":\"chapters\",\"results\":[" as *u8)
206 var first: i64 = 1
207 var pos: i64 = 0
208 var guard: i64 = 0
209 while guard < 400 {
210 guard = guard + 1
211 let idp: i64 = na_find_from(json, jn, "\"id\":\"" as *u8, pos)
212 if idp < 0 { guard = 400 } else {
213 let vs: i64 = idp + 6
214 let ve: i64 = na_find_from(json, jn, "\"" as *u8, vs)
215 if ve < 0 { guard = 400 } else {
216 pos = ve + 1
217 if mss_at(json, jn, ve, "\",\"type\":\"chapter\"" as *u8) == 1 {
218 let nextc: i64 = na_find_from(json, jn, "\"type\":\"chapter\"" as *u8, ve + 12)
219 var bound: i64 = jn; if nextc >= 0 { bound = nextc }
220 // chapter number
221 let cp: i64 = na_find_from(json, jn, "\"chapter\":\"" as *u8, ve)
222 var chs: i64 = 0; var che: i64 = 0
223 if cp >= 0 { if cp < bound { chs = cp + 11; che = na_find_from(json, jn, "\"" as *u8, chs) } }
224 if first == 0 { out[o] = 44 as u8; o = o + 1 }
225 first = 0
226 o = zs_apps(out, o, "{\"ch\":\"" as *u8)
227 if che > chs { var c: i64 = chs; while c < che { if o < cap-1 { out[o]=json[c] as u8; o=o+1 } c=c+1 } } else { o = zs_apps(out, o, "?" as *u8) }
228 o = zs_apps(out, o, "\",\"id\":\"" as *u8)
229 var c2: i64 = vs; while c2 < ve { if o < cap-1 { out[o]=json[c2] as u8; o=o+1 } c2=c2+1 }
230 o = zs_apps(out, o, "\"}" as *u8)
231 }
232 }
233 }
234 }
235 o = zs_apps(out, o, "]}" as *u8); out[o] = 0 as u8
236 return o
237}
238
239// urldecode enc[0..n) into dst (NUL-term). %XX + '+'->space. returns len.
240func mss_urldec(enc: *u8, n: i64, dst: *u8) -> i64 {
241 var i: i64 = 0; var o: i64 = 0
242 while i < n {
243 let c: i64 = enc[i] as i64
244 if c == 37 { if i + 2 < n {
245 let h1: i64 = enc[i+1] as i64; let h2: i64 = enc[i+2] as i64
246 var v1: i64 = h1-48; if h1>=97 {v1=h1-87} else { if h1>=65 {v1=h1-55} }
247 var v2: i64 = h2-48; if h2>=97 {v2=h2-87} else { if h2>=65 {v2=h2-55} }
248 dst[o] = ((v1*16)+v2) as u8; o=o+1; i=i+3
249 } else { i = n } }
250 else { if c == 43 { dst[o]=32 as u8; o=o+1; i=i+1 } else { dst[o]=enc[i] as u8; o=o+1; i=i+1 } }
251 }
252 dst[o] = 0 as u8
253 return o
254}
255
256// load the trust store (per-request; correctness-first). 0 on fail.
257func mss_store() -> i64 { return nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, MSS_MAGIC_4194304) }
258
259// shared: fetch `url` (Chrome-JA3), parse (mangadex vs nhentai), emit the results JSON. Used by search/browse/random.
260func mss_emit_results(cfd: i64, url: *u8, is_md: i64) -> i64 {
261 let store: i64 = mss_store()
262 if store <= 0 { return zs_emit(cfd, "500 Internal Server Error" as *u8, "{\"err\":\"store\"}" as *u8) }
263 let buf: *u8 = sys_mmap(MSS_FETCH_CAP); let st: *i64 = sys_mmap(8) as *i64
264 let n: i64 = nx_https_fetch_follow_chrome(url, store as *TrustStore, buf, MSS_FETCH_CAP, 6, st)
265 if n <= 0 { return zs_emit(cfd, "502 Bad Gateway" as *u8, "{\"err\":\"fetch\",\"results\":[]}" as *u8) }
266 let out: *u8 = sys_mmap(MSS_OUT_CAP)
267 if is_md == 1 { msearch_mangadex(buf, n, out, MSS_OUT_CAP) } else { msearch_nhentai(buf, n, out, MSS_OUT_CAP) }
268 return zs_emit(cfd, "200 OK" as *u8, out)
269}
270
271// GET /api/msearch?src=<s>&q=<q> -> results JSON
272func mss_handle_search(cfd: i64, path: *u8, plen: i64) -> i64 {
273 let src: *u8 = sys_mmap(32); zs_qval(path, plen, "src" as *u8, src, 32)
274 let qraw: *u8 = sys_mmap(512); let ql: i64 = zs_qval(path, plen, "q" as *u8, qraw, 512)
275 if ql <= 0 { return zs_emit(cfd, "200 OK" as *u8, "{\"results\":[]}" as *u8) }
276 let qd: *u8 = sys_mmap(512); let qdl: i64 = mss_urldec(qraw, ql, qd) // q arrives urlencoded in the path
277 let qe: *u8 = sys_mmap(MSS_MAGIC_1536); mss_qenc(qd, qdl, qe)
278 let url: *u8 = sys_mmap(MSS_MAGIC_2048); var uo: i64 = 0
279 var is_md: i64 = 0
280 if mss_at(src, 32, 0, "mangadex" as *u8) == 1 { is_md = 1 }
281 if is_md == 1 {
282 uo = zs_apps(url, 0, "https://api.mangadex.org/manga?title=" as *u8)
283 uo = zs_apps(url, uo, qe)
284 uo = zs_apps(url, uo, "&limit=24&includes[]=cover_art&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic" as *u8)
285 } else {
286 uo = zs_apps(url, 0, "https://nhentai.net/search/?q=" as *u8)
287 uo = zs_apps(url, uo, qe)
288 }
289 url[uo] = 0 as u8
290 return mss_emit_results(cfd, url, is_md)
291}
292
293// GET /api/mbrowse?src=<s>&mode=<popular|latest> -> the LANDING FEED (browse without typing; operator #1 ask).
294// Reuses the same parsers -- only the URL changes (mangadex order[], nhentai homepage = recent galleries).
295func mss_handle_browse(cfd: i64, path: *u8, plen: i64) -> i64 {
296 let src: *u8 = sys_mmap(32); zs_qval(path, plen, "src" as *u8, src, 32)
297 let mode: *u8 = sys_mmap(32); zs_qval(path, plen, "mode" as *u8, mode, 32)
298 var is_md: i64 = 0
299 if mss_at(src, 32, 0, "mangadex" as *u8) == 1 { is_md = 1 }
300 let url: *u8 = sys_mmap(MSS_MAGIC_2048); var uo: i64 = 0
301 if is_md == 1 {
302 uo = zs_apps(url, 0, "https://api.mangadex.org/manga?limit=24&includes[]=cover_art&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic&hasAvailableChapters=true&order[" as *u8)
303 if mss_at(mode, 32, 0, "latest" as *u8) == 1 { uo = zs_apps(url, uo, "latestUploadedChapter]=desc" as *u8) }
304 else { uo = zs_apps(url, uo, "followedCount]=desc" as *u8) }
305 } else {
306 // nhentai homepage = the recent-galleries feed (same card HTML the search parser reads)
307 uo = zs_apps(url, 0, "https://nhentai.net/" as *u8)
308 }
309 url[uo] = 0 as u8
310 return mss_emit_results(cfd, url, is_md)
311}
312
313// GET /api/mrandom?src=<s> -> ONE random title (mangadex /manga/random -> series card). operator: modern UI "random".
314func mss_handle_random(cfd: i64, path: *u8, plen: i64) -> i64 {
315 let src: *u8 = sys_mmap(32); zs_qval(path, plen, "src" as *u8, src, 32)
316 var is_md: i64 = 0
317 if mss_at(src, 32, 0, "mangadex" as *u8) == 1 { is_md = 1 }
318 let url: *u8 = sys_mmap(MSS_MAGIC_1024)
319 if is_md == 1 { zs_apps(url, 0, "https://api.mangadex.org/manga/random?includes[]=cover_art&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic" as *u8) }
320 else { zs_apps(url, 0, "https://nhentai.net/random/" as *u8) } // redirects to a /g/<id>/ gallery; parser reads it
321 return mss_emit_results(cfd, url, is_md)
322}
323
324// GET /api/mfeed?id=<mangaId> -> chapter list JSON (mangadex)
325func mss_handle_feed(cfd: i64, path: *u8, plen: i64) -> i64 {
326 let id: *u8 = sys_mmap(64); let idl: i64 = zs_qval(path, plen, "id" as *u8, id, 64)
327 if idl <= 0 { return zs_emit(cfd, "200 OK" as *u8, "{\"results\":[]}" as *u8) }
328 let url: *u8 = sys_mmap(MSS_MAGIC_1024); var uo: i64 = 0
329 uo = zs_apps(url, 0, "https://api.mangadex.org/manga/" as *u8)
330 uo = zs_apps(url, uo, id)
331 uo = zs_apps(url, uo, "/feed?translatedLanguage[]=en&order[chapter]=asc&limit=200&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic" as *u8)
332 url[uo] = 0 as u8
333 let store: i64 = mss_store()
334 if store <= 0 { return zs_emit(cfd, "500 Internal Server Error" as *u8, "{\"err\":\"store\"}" as *u8) }
335 let buf: *u8 = sys_mmap(MSS_FETCH_CAP); let st: *i64 = sys_mmap(8) as *i64
336 let n: i64 = nx_https_fetch_follow_chrome(url, store as *TrustStore, buf, MSS_FETCH_CAP, 6, st)
337 if n <= 0 { return zs_emit(cfd, "502 Bad Gateway" as *u8, "{\"err\":\"fetch\",\"results\":[]}" as *u8) }
338 let out: *u8 = sys_mmap(MSS_OUT_CAP)
339 mfeed_mangadex(buf, n, out, MSS_OUT_CAP)
340 return zs_emit(cfd, "200 OK" as *u8, out)
341}
342
343// GET /api/thumb?u=<enc url> -> proxy the image bytes (content-type from the magic). Small images only.
344func mss_handle_thumb(cfd: i64, path: *u8, plen: i64) -> i64 {
345 let enc: *u8 = sys_mmap(MSS_MAGIC_2048); let el: i64 = zs_qval(path, plen, "u" as *u8, enc, MSS_MAGIC_2048)
346 if el <= 0 { return zs_emit(cfd, "400 Bad Request" as *u8, "no u" as *u8) }
347 let u: *u8 = sys_mmap(MSS_MAGIC_2048); mss_urldec(enc, el, u)
348 // allow-list hosts (no open proxy): mangadex covers + nhentai thumbs only
349 var okhost: i64 = 0
350 if na_find_from(u, mss_slen(u), "uploads.mangadex.org/" as *u8, 0) >= 0 { okhost = 1 }
351 if na_find_from(u, mss_slen(u), ".nhentai.net/" as *u8, 0) >= 0 { okhost = 1 }
352 if okhost == 0 { return zs_emit(cfd, "403 Forbidden" as *u8, "host" as *u8) }
353 let store: i64 = mss_store()
354 if store <= 0 { return zs_emit(cfd, "500 Internal Server Error" as *u8, "store" as *u8) }
355 let buf: *u8 = sys_mmap(MSS_FETCH_CAP); let st: *i64 = sys_mmap(8) as *i64
356 let n: i64 = nx_https_fetch_follow_chrome(u, store as *TrustStore, buf, MSS_FETCH_CAP, 4, st)
357 if n <= 0 { return zs_emit(cfd, "502 Bad Gateway" as *u8, "fetch" as *u8) }
358 // content-type from magic
359 var ct: *u8 = "image/jpeg" as *u8
360 if n > 12 { if (buf[0] as i64)==0x89 { ct = "image/png" as *u8 } if (buf[0] as i64)==0x47 { ct = "image/gif" as *u8 } if (buf[0] as i64)==0x52 { if (buf[8] as i64)==0x57 { ct = "image/webp" as *u8 } } }
361 let hdr: *u8 = sys_mmap(256); var ho: i64 = 0
362 ho = zs_apps(hdr, 0, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8)
363 ho = zs_apps(hdr, ho, ct)
364 ho = zs_apps(hdr, ho, "\r\nCache-Control: max-age=86400\r\nContent-Length: " as *u8)
365 ho = zs_dec(hdr, ho, n)
366 ho = zs_apps(hdr, ho, "\r\nConnection: close\r\n\r\n" as *u8)
367 sys_write(cfd, hdr, ho)
368 sys_write(cfd, buf, n)
369 sys_close(cfd)
370 return 0
371}