kibi-swipl-linux-x64-gnu 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (550) hide show
  1. package/README.md +29 -0
  2. package/bin/swipl +0 -0
  3. package/bin/swipl-win +0 -0
  4. package/build-manifest.json +70 -0
  5. package/lib/cmake/swipl/SWIPLConfig.cmake +21 -0
  6. package/lib/cmake/swipl/SWIPLConfigVersion.cmake +65 -0
  7. package/lib/cmake/swipl/SWIPLTargets-release.cmake +28 -0
  8. package/lib/cmake/swipl/SWIPLTargets.cmake +109 -0
  9. package/lib/swipl/ABI +1 -0
  10. package/lib/swipl/LICENSE +41 -0
  11. package/lib/swipl/README.md +116 -0
  12. package/lib/swipl/app/README.md +25 -0
  13. package/lib/swipl/app/app.pl +87 -0
  14. package/lib/swipl/app/pack.pl +350 -0
  15. package/lib/swipl/app/qlf.pl +521 -0
  16. package/lib/swipl/app/splfr.pl +177 -0
  17. package/lib/swipl/app/sys.pl +310 -0
  18. package/lib/swipl/bin/swipl.home +1 -0
  19. package/lib/swipl/boot/apply.pl +73 -0
  20. package/lib/swipl/boot/attvar.pl +344 -0
  21. package/lib/swipl/boot/autoload.pl +1226 -0
  22. package/lib/swipl/boot/bags.pl +283 -0
  23. package/lib/swipl/boot/dcg.pl +388 -0
  24. package/lib/swipl/boot/dicts.pl +193 -0
  25. package/lib/swipl/boot/dwim.pl +485 -0
  26. package/lib/swipl/boot/engines.pl +152 -0
  27. package/lib/swipl/boot/expand.pl +1628 -0
  28. package/lib/swipl/boot/gc.pl +65 -0
  29. package/lib/swipl/boot/history.pl +304 -0
  30. package/lib/swipl/boot/init.pl +4682 -0
  31. package/lib/swipl/boot/iri.pl +64 -0
  32. package/lib/swipl/boot/license.pl +390 -0
  33. package/lib/swipl/boot/load.pl +81 -0
  34. package/lib/swipl/boot/messages.pl +2521 -0
  35. package/lib/swipl/boot/packs.pl +306 -0
  36. package/lib/swipl/boot/predopts.pl +154 -0
  37. package/lib/swipl/boot/qlf.pl +141 -0
  38. package/lib/swipl/boot/rc.pl +263 -0
  39. package/lib/swipl/boot/syspred.pl +1634 -0
  40. package/lib/swipl/boot/tabling.pl +2321 -0
  41. package/lib/swipl/boot/threads.pl +42 -0
  42. package/lib/swipl/boot/toplevel.pl +2248 -0
  43. package/lib/swipl/boot/topvars.pl +261 -0
  44. package/lib/swipl/boot.prc +0 -0
  45. package/lib/swipl/cmake/swipl.cmake +131 -0
  46. package/lib/swipl/customize/README.md +23 -0
  47. package/lib/swipl/customize/edit +101 -0
  48. package/lib/swipl/customize/init.pl +164 -0
  49. package/lib/swipl/demo/README.md +33 -0
  50. package/lib/swipl/demo/likes.pl +44 -0
  51. package/lib/swipl/doc/packages/examples/chr/bool.chr +281 -0
  52. package/lib/swipl/doc/packages/examples/chr/chrdif.chr +87 -0
  53. package/lib/swipl/doc/packages/examples/chr/chrfreeze.chr +6 -0
  54. package/lib/swipl/doc/packages/examples/chr/family.chr +116 -0
  55. package/lib/swipl/doc/packages/examples/chr/fib.chr +24 -0
  56. package/lib/swipl/doc/packages/examples/chr/fibonacci.chr +31 -0
  57. package/lib/swipl/doc/packages/examples/chr/gcd.chr +28 -0
  58. package/lib/swipl/doc/packages/examples/chr/leq.chr +34 -0
  59. package/lib/swipl/doc/packages/examples/chr/listdom.chr +138 -0
  60. package/lib/swipl/doc/packages/examples/chr/primes.chr +29 -0
  61. package/lib/swipl/doc/packages/examples/http/README.md +98 -0
  62. package/lib/swipl/doc/packages/examples/http/calc.pl +92 -0
  63. package/lib/swipl/doc/packages/examples/http/demo_body.pl +232 -0
  64. package/lib/swipl/doc/packages/examples/http/demo_client.pl +165 -0
  65. package/lib/swipl/doc/packages/examples/http/demo_daemon.pl +38 -0
  66. package/lib/swipl/doc/packages/examples/http/demo_files.pl +50 -0
  67. package/lib/swipl/doc/packages/examples/http/demo_hello.pl +15 -0
  68. package/lib/swipl/doc/packages/examples/http/demo_login.pl +280 -0
  69. package/lib/swipl/doc/packages/examples/http/demo_openid.pl +177 -0
  70. package/lib/swipl/doc/packages/examples/http/demo_pwp.pl +20 -0
  71. package/lib/swipl/doc/packages/examples/http/demo_rest.pl +56 -0
  72. package/lib/swipl/doc/packages/examples/http/demo_threads.pl +52 -0
  73. package/lib/swipl/doc/packages/examples/http/linux-init-script +126 -0
  74. package/lib/swipl/doc/packages/examples/http/pwp/context.pwp +23 -0
  75. package/lib/swipl/doc/packages/examples/http/pwp/index.pwp +25 -0
  76. package/lib/swipl/doc/packages/examples/http/pwp/pwp1.pwp +12 -0
  77. package/lib/swipl/doc/packages/examples/http/pwp/pwp2.pwp +10 -0
  78. package/lib/swipl/doc/packages/examples/http/pwp/pwp3.pwp +25 -0
  79. package/lib/swipl/doc/packages/examples/http/pwp/pwp4.pwp +23 -0
  80. package/lib/swipl/doc/packages/examples/http/pwp/pwp5.pwp +11 -0
  81. package/lib/swipl/doc/packages/examples/http/pwp/pwp6.pwp +3 -0
  82. package/lib/swipl/doc/packages/examples/http/pwp/pwp7.pwp +3 -0
  83. package/lib/swipl/doc/packages/examples/http/pwp/pwp8.pwp +3 -0
  84. package/lib/swipl/doc/packages/examples/http/pwp/pwpdb.pl +12 -0
  85. package/lib/swipl/doc/packages/examples/http/systemd-script.service +18 -0
  86. package/lib/swipl/doc/packages/examples/http/upstart-script.conf +20 -0
  87. package/lib/swipl/doc/packages/examples/plunit/read.pl +17 -0
  88. package/lib/swipl/doc/packages/examples/plunit/simple.pl +33 -0
  89. package/lib/swipl/doc/packages/examples/ssl/client.pl +83 -0
  90. package/lib/swipl/doc/packages/examples/ssl/etc/README +52 -0
  91. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.p12 +0 -0
  92. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.pem +85 -0
  93. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-key.pem +30 -0
  94. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/cacert.pem +82 -0
  95. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/careq.pem +18 -0
  96. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/crlnumber +1 -0
  97. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt +3 -0
  98. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt.attr +1 -0
  99. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7C.pem +85 -0
  100. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7D.pem +85 -0
  101. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/private/cakey.pem +30 -0
  102. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/serial +1 -0
  103. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-cert.pem +85 -0
  104. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-key.pem +30 -0
  105. package/lib/swipl/doc/packages/examples/ssl/https.pl +267 -0
  106. package/lib/swipl/doc/packages/examples/ssl/server.pl +106 -0
  107. package/lib/swipl/include/SWI-Prolog.h +1544 -0
  108. package/lib/swipl/include/SWI-Stream.h +537 -0
  109. package/lib/swipl/include/Yap/YapInterface.h +283 -0
  110. package/lib/swipl/include/sicstus/sicstus.h +452 -0
  111. package/lib/swipl/lib/x86_64-linux/cgi.so +0 -0
  112. package/lib/swipl/lib/x86_64-linux/crypt.so +0 -0
  113. package/lib/swipl/lib/x86_64-linux/crypto4pl.so +0 -0
  114. package/lib/swipl/lib/x86_64-linux/double_metaphone.so +0 -0
  115. package/lib/swipl/lib/x86_64-linux/files.so +0 -0
  116. package/lib/swipl/lib/x86_64-linux/hashstream.so +0 -0
  117. package/lib/swipl/lib/x86_64-linux/http_stream.so +0 -0
  118. package/lib/swipl/lib/x86_64-linux/isub.so +0 -0
  119. package/lib/swipl/lib/x86_64-linux/json.so +0 -0
  120. package/lib/swipl/lib/x86_64-linux/libswipl.so.10 +0 -0
  121. package/lib/swipl/lib/x86_64-linux/mallocinfo.so +0 -0
  122. package/lib/swipl/lib/x86_64-linux/md54pl.so +0 -0
  123. package/lib/swipl/lib/x86_64-linux/memfile.so +0 -0
  124. package/lib/swipl/lib/x86_64-linux/ntriples.so +0 -0
  125. package/lib/swipl/lib/x86_64-linux/pcre4pl.so +0 -0
  126. package/lib/swipl/lib/x86_64-linux/porter_stem.so +0 -0
  127. package/lib/swipl/lib/x86_64-linux/process.so +0 -0
  128. package/lib/swipl/lib/x86_64-linux/prolog_stream.so +0 -0
  129. package/lib/swipl/lib/x86_64-linux/rdf_db.so +0 -0
  130. package/lib/swipl/lib/x86_64-linux/readutil.so +0 -0
  131. package/lib/swipl/lib/x86_64-linux/rlimit.so +0 -0
  132. package/lib/swipl/lib/x86_64-linux/sched.so +0 -0
  133. package/lib/swipl/lib/x86_64-linux/sgml2pl.so +0 -0
  134. package/lib/swipl/lib/x86_64-linux/sha4pl.so +0 -0
  135. package/lib/swipl/lib/x86_64-linux/snowball.so +0 -0
  136. package/lib/swipl/lib/x86_64-linux/socket.so +0 -0
  137. package/lib/swipl/lib/x86_64-linux/ssl4pl.so +0 -0
  138. package/lib/swipl/lib/x86_64-linux/streaminfo.so +0 -0
  139. package/lib/swipl/lib/x86_64-linux/syslog.so +0 -0
  140. package/lib/swipl/lib/x86_64-linux/time.so +0 -0
  141. package/lib/swipl/lib/x86_64-linux/turtle.so +0 -0
  142. package/lib/swipl/lib/x86_64-linux/uid.so +0 -0
  143. package/lib/swipl/lib/x86_64-linux/unix.so +0 -0
  144. package/lib/swipl/lib/x86_64-linux/uri.so +0 -0
  145. package/lib/swipl/lib/x86_64-linux/websocket.so +0 -0
  146. package/lib/swipl/lib/x86_64-linux/zlib4pl.so +0 -0
  147. package/lib/swipl/library/INDEX.pl +1020 -0
  148. package/lib/swipl/library/aggregate.pl +755 -0
  149. package/lib/swipl/library/ansi_term.pl +653 -0
  150. package/lib/swipl/library/apply.pl +426 -0
  151. package/lib/swipl/library/apply_macros.pl +497 -0
  152. package/lib/swipl/library/arithmetic.pl +320 -0
  153. package/lib/swipl/library/assoc.pl +522 -0
  154. package/lib/swipl/library/atom.pl +169 -0
  155. package/lib/swipl/library/backcomp.pl +688 -0
  156. package/lib/swipl/library/base32.pl +291 -0
  157. package/lib/swipl/library/base64.pl +441 -0
  158. package/lib/swipl/library/broadcast.pl +161 -0
  159. package/lib/swipl/library/build/cmake.pl +137 -0
  160. package/lib/swipl/library/build/conan.pl +232 -0
  161. package/lib/swipl/library/build/make.pl +168 -0
  162. package/lib/swipl/library/build/tools.pl +825 -0
  163. package/lib/swipl/library/charsio.pl +195 -0
  164. package/lib/swipl/library/check.pl +1097 -0
  165. package/lib/swipl/library/check_installation.pl +912 -0
  166. package/lib/swipl/library/clp/INDEX.pl +157 -0
  167. package/lib/swipl/library/clp/bounds.pl +2036 -0
  168. package/lib/swipl/library/clp/clp_distinct.pl +263 -0
  169. package/lib/swipl/library/clp/clp_events.pl +92 -0
  170. package/lib/swipl/library/clp/clpb.pl +1896 -0
  171. package/lib/swipl/library/clp/clpfd.pl +7906 -0
  172. package/lib/swipl/library/clp/simplex.pl +1580 -0
  173. package/lib/swipl/library/codesio.pl +182 -0
  174. package/lib/swipl/library/coinduction.pl +183 -0
  175. package/lib/swipl/library/console_input.pl +289 -0
  176. package/lib/swipl/library/csv.pl +611 -0
  177. package/lib/swipl/library/ctypes.pl +161 -0
  178. package/lib/swipl/library/date.pl +370 -0
  179. package/lib/swipl/library/dcg/INDEX.pl +35 -0
  180. package/lib/swipl/library/dcg/basics.pl +514 -0
  181. package/lib/swipl/library/dcg/high_order.pl +227 -0
  182. package/lib/swipl/library/debug.pl +499 -0
  183. package/lib/swipl/library/dialect/bim.pl +186 -0
  184. package/lib/swipl/library/dialect/commons.pl +77 -0
  185. package/lib/swipl/library/dialect/eclipse/test_util_iso.pl +355 -0
  186. package/lib/swipl/library/dialect/hprolog/format.pl +44 -0
  187. package/lib/swipl/library/dialect/hprolog.pl +314 -0
  188. package/lib/swipl/library/dialect/ifprolog.pl +1317 -0
  189. package/lib/swipl/library/dialect/iso/iso_predicates.pl +277 -0
  190. package/lib/swipl/library/dialect/sicstus/README.TXT +1 -0
  191. package/lib/swipl/library/dialect/sicstus/arrays.pl +121 -0
  192. package/lib/swipl/library/dialect/sicstus/block.pl +278 -0
  193. package/lib/swipl/library/dialect/sicstus/lists.pl +167 -0
  194. package/lib/swipl/library/dialect/sicstus/ordsets.pl +52 -0
  195. package/lib/swipl/library/dialect/sicstus/sockets.pl +174 -0
  196. package/lib/swipl/library/dialect/sicstus/system.pl +262 -0
  197. package/lib/swipl/library/dialect/sicstus/terms.pl +57 -0
  198. package/lib/swipl/library/dialect/sicstus/timeout.pl +92 -0
  199. package/lib/swipl/library/dialect/sicstus.pl +582 -0
  200. package/lib/swipl/library/dialect/sicstus4/aggregate.pl +60 -0
  201. package/lib/swipl/library/dialect/sicstus4/between.pl +62 -0
  202. package/lib/swipl/library/dialect/sicstus4/clpfd.pl +75 -0
  203. package/lib/swipl/library/dialect/sicstus4/file_systems.pl +413 -0
  204. package/lib/swipl/library/dialect/sicstus4/lists.pl +274 -0
  205. package/lib/swipl/library/dialect/sicstus4/ordsets.pl +54 -0
  206. package/lib/swipl/library/dialect/sicstus4/samsort.pl +86 -0
  207. package/lib/swipl/library/dialect/sicstus4/sets.pl +124 -0
  208. package/lib/swipl/library/dialect/sicstus4/sockets.pl +164 -0
  209. package/lib/swipl/library/dialect/sicstus4/system.pl +80 -0
  210. package/lib/swipl/library/dialect/sicstus4/terms.pl +89 -0
  211. package/lib/swipl/library/dialect/sicstus4/timeout.pl +43 -0
  212. package/lib/swipl/library/dialect/sicstus4/types.pl +103 -0
  213. package/lib/swipl/library/dialect/sicstus4.pl +200 -0
  214. package/lib/swipl/library/dialect/swi/syspred_options.pl +250 -0
  215. package/lib/swipl/library/dialect/xsb/README.md +20 -0
  216. package/lib/swipl/library/dialect/xsb/basics.pl +318 -0
  217. package/lib/swipl/library/dialect/xsb/consult.pl +87 -0
  218. package/lib/swipl/library/dialect/xsb/curr_sym.pl +57 -0
  219. package/lib/swipl/library/dialect/xsb/error_handler.pl +111 -0
  220. package/lib/swipl/library/dialect/xsb/gensym.pl +53 -0
  221. package/lib/swipl/library/dialect/xsb/gpp.pl +138 -0
  222. package/lib/swipl/library/dialect/xsb/intern.pl +48 -0
  223. package/lib/swipl/library/dialect/xsb/lists.pl +47 -0
  224. package/lib/swipl/library/dialect/xsb/machine.pl +295 -0
  225. package/lib/swipl/library/dialect/xsb/ordsets.pl +53 -0
  226. package/lib/swipl/library/dialect/xsb/setof.pl +54 -0
  227. package/lib/swipl/library/dialect/xsb/source.pl +308 -0
  228. package/lib/swipl/library/dialect/xsb/standard.pl +169 -0
  229. package/lib/swipl/library/dialect/xsb/storage.pl +70 -0
  230. package/lib/swipl/library/dialect/xsb/string.pl +76 -0
  231. package/lib/swipl/library/dialect/xsb/thread.pl +62 -0
  232. package/lib/swipl/library/dialect/xsb/timed_call.pl +158 -0
  233. package/lib/swipl/library/dialect/xsb.pl +688 -0
  234. package/lib/swipl/library/dialect/yap/README.TXT +8 -0
  235. package/lib/swipl/library/dialect/yap.pl +283 -0
  236. package/lib/swipl/library/dialect.pl +123 -0
  237. package/lib/swipl/library/dicts.pl +399 -0
  238. package/lib/swipl/library/dif.pl +426 -0
  239. package/lib/swipl/library/edinburgh.pl +138 -0
  240. package/lib/swipl/library/edit.pl +783 -0
  241. package/lib/swipl/library/error.pl +495 -0
  242. package/lib/swipl/library/exceptions.pl +231 -0
  243. package/lib/swipl/library/explain.pl +543 -0
  244. package/lib/swipl/library/ext/RDF/INDEX.pl +25 -0
  245. package/lib/swipl/library/ext/RDF/rdf.pl +450 -0
  246. package/lib/swipl/library/ext/RDF/rdf_parser.pl +649 -0
  247. package/lib/swipl/library/ext/RDF/rdf_triple.pl +448 -0
  248. package/lib/swipl/library/ext/RDF/rdf_write.pl +701 -0
  249. package/lib/swipl/library/ext/RDF/rewrite_term.pl +177 -0
  250. package/lib/swipl/library/ext/chr/chr/a_star.pl +80 -0
  251. package/lib/swipl/library/ext/chr/chr/binomialheap.pl +142 -0
  252. package/lib/swipl/library/ext/chr/chr/builtins.pl +629 -0
  253. package/lib/swipl/library/ext/chr/chr/chr_compiler_errors.pl +179 -0
  254. package/lib/swipl/library/ext/chr/chr/chr_compiler_options.pl +382 -0
  255. package/lib/swipl/library/ext/chr/chr/chr_compiler_utility.pl +338 -0
  256. package/lib/swipl/library/ext/chr/chr/chr_debug.pl +59 -0
  257. package/lib/swipl/library/ext/chr/chr/chr_hashtable_store.pl +425 -0
  258. package/lib/swipl/library/ext/chr/chr/chr_integertable_store.pl +139 -0
  259. package/lib/swipl/library/ext/chr/chr/chr_messages.pl +176 -0
  260. package/lib/swipl/library/ext/chr/chr/chr_op.pl +53 -0
  261. package/lib/swipl/library/ext/chr/chr/chr_runtime.pl +1016 -0
  262. package/lib/swipl/library/ext/chr/chr/chr_translate.pl +25424 -0
  263. package/lib/swipl/library/ext/chr/chr/clean_code.pl +252 -0
  264. package/lib/swipl/library/ext/chr/chr/find.pl +78 -0
  265. package/lib/swipl/library/ext/chr/chr/guard_entailment.pl +19432 -0
  266. package/lib/swipl/library/ext/chr/chr/listmap.pl +108 -0
  267. package/lib/swipl/library/ext/chr/chr/pairlist.pl +78 -0
  268. package/lib/swipl/library/ext/chr/chr.pl +686 -0
  269. package/lib/swipl/library/ext/clib/INDEX.pl +158 -0
  270. package/lib/swipl/library/ext/clib/cgi.pl +86 -0
  271. package/lib/swipl/library/ext/clib/crypt.pl +44 -0
  272. package/lib/swipl/library/ext/clib/filesex.pl +644 -0
  273. package/lib/swipl/library/ext/clib/hash_stream.pl +119 -0
  274. package/lib/swipl/library/ext/clib/mallocinfo.pl +138 -0
  275. package/lib/swipl/library/ext/clib/md5.pl +68 -0
  276. package/lib/swipl/library/ext/clib/memfile.pl +61 -0
  277. package/lib/swipl/library/ext/clib/process.pl +573 -0
  278. package/lib/swipl/library/ext/clib/prolog_server.pl +157 -0
  279. package/lib/swipl/library/ext/clib/prolog_stream.pl +80 -0
  280. package/lib/swipl/library/ext/clib/rlimit.pl +54 -0
  281. package/lib/swipl/library/ext/clib/sched.pl +85 -0
  282. package/lib/swipl/library/ext/clib/sha.pl +162 -0
  283. package/lib/swipl/library/ext/clib/socket.pl +1102 -0
  284. package/lib/swipl/library/ext/clib/streaminfo.pl +103 -0
  285. package/lib/swipl/library/ext/clib/streampool.pl +136 -0
  286. package/lib/swipl/library/ext/clib/syslog.pl +180 -0
  287. package/lib/swipl/library/ext/clib/time.pl +194 -0
  288. package/lib/swipl/library/ext/clib/udp_broadcast.pl +975 -0
  289. package/lib/swipl/library/ext/clib/uid.pl +220 -0
  290. package/lib/swipl/library/ext/clib/unix.pl +317 -0
  291. package/lib/swipl/library/ext/clib/uri.pl +530 -0
  292. package/lib/swipl/library/ext/clib/uuid.pl +207 -0
  293. package/lib/swipl/library/ext/http/http/INDEX.pl +266 -0
  294. package/lib/swipl/library/ext/http/http/README.md +34 -0
  295. package/lib/swipl/library/ext/http/http/ax.pl +189 -0
  296. package/lib/swipl/library/ext/http/http/dcg_basics.pl +49 -0
  297. package/lib/swipl/library/ext/http/http/graphql.pl +1367 -0
  298. package/lib/swipl/library/ext/http/http/html_decl.pl +416 -0
  299. package/lib/swipl/library/ext/http/http/html_head.pl +654 -0
  300. package/lib/swipl/library/ext/http/http/html_quasiquotations.pl +120 -0
  301. package/lib/swipl/library/ext/http/http/html_write.pl +1425 -0
  302. package/lib/swipl/library/ext/http/http/htmx.pl +139 -0
  303. package/lib/swipl/library/ext/http/http/http_authenticate.pl +364 -0
  304. package/lib/swipl/library/ext/http/http/http_client.pl +412 -0
  305. package/lib/swipl/library/ext/http/http/http_cookie.pl +245 -0
  306. package/lib/swipl/library/ext/http/http/http_cors.pl +176 -0
  307. package/lib/swipl/library/ext/http/http/http_digest.pl +820 -0
  308. package/lib/swipl/library/ext/http/http/http_dirindex.pl +296 -0
  309. package/lib/swipl/library/ext/http/http/http_dispatch.pl +1552 -0
  310. package/lib/swipl/library/ext/http/http/http_dyn_workers.pl +214 -0
  311. package/lib/swipl/library/ext/http/http/http_error.pl +126 -0
  312. package/lib/swipl/library/ext/http/http/http_exception.pl +225 -0
  313. package/lib/swipl/library/ext/http/http/http_files.pl +163 -0
  314. package/lib/swipl/library/ext/http/http/http_header.pl +2820 -0
  315. package/lib/swipl/library/ext/http/http/http_hook.pl +106 -0
  316. package/lib/swipl/library/ext/http/http/http_host.pl +204 -0
  317. package/lib/swipl/library/ext/http/http/http_load.pl +113 -0
  318. package/lib/swipl/library/ext/http/http/http_log.pl +738 -0
  319. package/lib/swipl/library/ext/http/http/http_multipart_plugin.pl +232 -0
  320. package/lib/swipl/library/ext/http/http/http_open.pl +1821 -0
  321. package/lib/swipl/library/ext/http/http/http_openid.pl +1561 -0
  322. package/lib/swipl/library/ext/http/http/http_parameters.pl +504 -0
  323. package/lib/swipl/library/ext/http/http/http_path.pl +380 -0
  324. package/lib/swipl/library/ext/http/http/http_proxy.pl +80 -0
  325. package/lib/swipl/library/ext/http/http/http_pwp.pl +351 -0
  326. package/lib/swipl/library/ext/http/http/http_redis_plugin.pl +332 -0
  327. package/lib/swipl/library/ext/http/http/http_server.pl +105 -0
  328. package/lib/swipl/library/ext/http/http/http_server_files.pl +126 -0
  329. package/lib/swipl/library/ext/http/http/http_server_health.pl +186 -0
  330. package/lib/swipl/library/ext/http/http/http_session.pl +1040 -0
  331. package/lib/swipl/library/ext/http/http/http_sgml_plugin.pl +137 -0
  332. package/lib/swipl/library/ext/http/http/http_stream.pl +376 -0
  333. package/lib/swipl/library/ext/http/http/http_unix_daemon.pl +989 -0
  334. package/lib/swipl/library/ext/http/http/http_wrapper.pl +559 -0
  335. package/lib/swipl/library/ext/http/http/hub.pl +600 -0
  336. package/lib/swipl/library/ext/http/http/js_write.pl +461 -0
  337. package/lib/swipl/library/ext/http/http/mimepack.pl +224 -0
  338. package/lib/swipl/library/ext/http/http/mimetype.pl +276 -0
  339. package/lib/swipl/library/ext/http/http/term_html.pl +797 -0
  340. package/lib/swipl/library/ext/http/http/thread_httpd.pl +1181 -0
  341. package/lib/swipl/library/ext/http/http/web/css/dirindex.css +24 -0
  342. package/lib/swipl/library/ext/http/http/web/css/openid.css +57 -0
  343. package/lib/swipl/library/ext/http/http/web/icons/back.png +0 -0
  344. package/lib/swipl/library/ext/http/http/web/icons/c.png +0 -0
  345. package/lib/swipl/library/ext/http/http/web/icons/compressed.png +0 -0
  346. package/lib/swipl/library/ext/http/http/web/icons/folder.png +0 -0
  347. package/lib/swipl/library/ext/http/http/web/icons/generic.png +0 -0
  348. package/lib/swipl/library/ext/http/http/web/icons/layout.png +0 -0
  349. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-square.png +0 -0
  350. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-tiny.png +0 -0
  351. package/lib/swipl/library/ext/http/http/websocket.pl +729 -0
  352. package/lib/swipl/library/ext/http/http/yadis.pl +205 -0
  353. package/lib/swipl/library/ext/json/INDEX.pl +36 -0
  354. package/lib/swipl/library/ext/json/http/INDEX.pl +16 -0
  355. package/lib/swipl/library/ext/json/http/http_json.pl +490 -0
  356. package/lib/swipl/library/ext/json/http/js_grammar.pl +53 -0
  357. package/lib/swipl/library/ext/json/http/json.pl +48 -0
  358. package/lib/swipl/library/ext/json/http/json_convert.pl +48 -0
  359. package/lib/swipl/library/ext/json/json.pl +1215 -0
  360. package/lib/swipl/library/ext/json/json_convert.pl +681 -0
  361. package/lib/swipl/library/ext/json/json_grammar.pl +349 -0
  362. package/lib/swipl/library/ext/json/json_rpc_client.pl +423 -0
  363. package/lib/swipl/library/ext/json/json_rpc_common.pl +104 -0
  364. package/lib/swipl/library/ext/json/json_rpc_server.pl +489 -0
  365. package/lib/swipl/library/ext/json/json_schema.pl +2111 -0
  366. package/lib/swipl/library/ext/nlp/INDEX.pl +15 -0
  367. package/lib/swipl/library/ext/nlp/double_metaphone.pl +86 -0
  368. package/lib/swipl/library/ext/nlp/isub.pl +162 -0
  369. package/lib/swipl/library/ext/nlp/porter_stem.pl +50 -0
  370. package/lib/swipl/library/ext/nlp/snowball.pl +97 -0
  371. package/lib/swipl/library/ext/pcre/INDEX.pl +17 -0
  372. package/lib/swipl/library/ext/pcre/pcre.pl +974 -0
  373. package/lib/swipl/library/ext/plunit/INDEX.pl +20 -0
  374. package/lib/swipl/library/ext/plunit/plunit.pl +2631 -0
  375. package/lib/swipl/library/ext/plunit/test_wizard.pl +249 -0
  376. package/lib/swipl/library/ext/semweb/semweb/INDEX.pl +288 -0
  377. package/lib/swipl/library/ext/semweb/semweb/rdf11.pl +2106 -0
  378. package/lib/swipl/library/ext/semweb/semweb/rdf11_containers.pl +299 -0
  379. package/lib/swipl/library/ext/semweb/semweb/rdf_cache.pl +278 -0
  380. package/lib/swipl/library/ext/semweb/semweb/rdf_compare.pl +132 -0
  381. package/lib/swipl/library/ext/semweb/semweb/rdf_db.pl +3468 -0
  382. package/lib/swipl/library/ext/semweb/semweb/rdf_edit.pl +1145 -0
  383. package/lib/swipl/library/ext/semweb/semweb/rdf_http_plugin.pl +274 -0
  384. package/lib/swipl/library/ext/semweb/semweb/rdf_library.pl +1021 -0
  385. package/lib/swipl/library/ext/semweb/semweb/rdf_litindex.pl +1035 -0
  386. package/lib/swipl/library/ext/semweb/semweb/rdf_ntriples.pl +422 -0
  387. package/lib/swipl/library/ext/semweb/semweb/rdf_persistency.pl +1576 -0
  388. package/lib/swipl/library/ext/semweb/semweb/rdf_portray.pl +182 -0
  389. package/lib/swipl/library/ext/semweb/semweb/rdf_prefixes.pl +681 -0
  390. package/lib/swipl/library/ext/semweb/semweb/rdf_sandbox.pl +153 -0
  391. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle.pl +54 -0
  392. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle_write.pl +1587 -0
  393. package/lib/swipl/library/ext/semweb/semweb/rdf_zlib_plugin.pl +52 -0
  394. package/lib/swipl/library/ext/semweb/semweb/rdfa.pl +1510 -0
  395. package/lib/swipl/library/ext/semweb/semweb/rdfs.pl +475 -0
  396. package/lib/swipl/library/ext/semweb/semweb/sparql_client.pl +643 -0
  397. package/lib/swipl/library/ext/semweb/semweb/turtle.pl +455 -0
  398. package/lib/swipl/library/ext/sgml/DTD/HTML4.dcl +88 -0
  399. package/lib/swipl/library/ext/sgml/DTD/HTML4.dtd +1092 -0
  400. package/lib/swipl/library/ext/sgml/DTD/HTML4.soc +6 -0
  401. package/lib/swipl/library/ext/sgml/DTD/HTML5.dtd +906 -0
  402. package/lib/swipl/library/ext/sgml/DTD/HTMLlat1.ent +195 -0
  403. package/lib/swipl/library/ext/sgml/DTD/HTMLspec.ent +77 -0
  404. package/lib/swipl/library/ext/sgml/DTD/HTMLsym.ent +241 -0
  405. package/lib/swipl/library/ext/sgml/INDEX.pl +64 -0
  406. package/lib/swipl/library/ext/sgml/c14n2.pl +203 -0
  407. package/lib/swipl/library/ext/sgml/iso_639.pl +631 -0
  408. package/lib/swipl/library/ext/sgml/pwp.pl +705 -0
  409. package/lib/swipl/library/ext/sgml/sgml.pl +815 -0
  410. package/lib/swipl/library/ext/sgml/sgml_write.pl +1003 -0
  411. package/lib/swipl/library/ext/sgml/xpath.pl +620 -0
  412. package/lib/swipl/library/ext/sgml/xsdp_types.pl +232 -0
  413. package/lib/swipl/library/ext/ssl/INDEX.pl +60 -0
  414. package/lib/swipl/library/ext/ssl/crypto.pl +1015 -0
  415. package/lib/swipl/library/ext/ssl/http/INDEX.pl +5 -0
  416. package/lib/swipl/library/ext/ssl/http/http_ssl_plugin.pl +296 -0
  417. package/lib/swipl/library/ext/ssl/saml.pl +609 -0
  418. package/lib/swipl/library/ext/ssl/ssl.pl +647 -0
  419. package/lib/swipl/library/ext/ssl/xmldsig.pl +391 -0
  420. package/lib/swipl/library/ext/ssl/xmlenc.pl +354 -0
  421. package/lib/swipl/library/ext/zlib/INDEX.pl +8 -0
  422. package/lib/swipl/library/ext/zlib/zlib.pl +112 -0
  423. package/lib/swipl/library/fastrw.pl +105 -0
  424. package/lib/swipl/library/files.pl +80 -0
  425. package/lib/swipl/library/gensym.pl +111 -0
  426. package/lib/swipl/library/git.pl +1027 -0
  427. package/lib/swipl/library/hashtable.pl +365 -0
  428. package/lib/swipl/library/heaps.pl +252 -0
  429. package/lib/swipl/library/hotfix.pl +239 -0
  430. package/lib/swipl/library/http/jquery.pl +103 -0
  431. package/lib/swipl/library/http/web/js/jquery-3.6.0.min.js +2 -0
  432. package/lib/swipl/library/increval.pl +217 -0
  433. package/lib/swipl/library/intercept.pl +263 -0
  434. package/lib/swipl/library/iostream.pl +237 -0
  435. package/lib/swipl/library/iri_scheme/file.pl +70 -0
  436. package/lib/swipl/library/lazy_lists.pl +481 -0
  437. package/lib/swipl/library/listing.pl +1362 -0
  438. package/lib/swipl/library/lists.pl +860 -0
  439. package/lib/swipl/library/lynx/INDEX.pl +14 -0
  440. package/lib/swipl/library/lynx/format.pl +380 -0
  441. package/lib/swipl/library/lynx/html_style.pl +129 -0
  442. package/lib/swipl/library/lynx/html_text.pl +865 -0
  443. package/lib/swipl/library/lynx/pldoc_style.pl +87 -0
  444. package/lib/swipl/library/macros.pl +451 -0
  445. package/lib/swipl/library/main.pl +1200 -0
  446. package/lib/swipl/library/make.pl +197 -0
  447. package/lib/swipl/library/modules.pl +129 -0
  448. package/lib/swipl/library/nb_rbtrees.pl +267 -0
  449. package/lib/swipl/library/nb_set.pl +203 -0
  450. package/lib/swipl/library/obfuscate.pl +115 -0
  451. package/lib/swipl/library/occurs.pl +241 -0
  452. package/lib/swipl/library/operators.pl +182 -0
  453. package/lib/swipl/library/option.pl +388 -0
  454. package/lib/swipl/library/optparse.pl +966 -0
  455. package/lib/swipl/library/ordsets.pl +518 -0
  456. package/lib/swipl/library/oset.pl +160 -0
  457. package/lib/swipl/library/pairs.pl +187 -0
  458. package/lib/swipl/library/persistency.pl +713 -0
  459. package/lib/swipl/library/pio.pl +47 -0
  460. package/lib/swipl/library/portray_text.pl +277 -0
  461. package/lib/swipl/library/pprint.pl +940 -0
  462. package/lib/swipl/library/predicate_options.pl +975 -0
  463. package/lib/swipl/library/prolog_autoload.pl +233 -0
  464. package/lib/swipl/library/prolog_breakpoints.pl +396 -0
  465. package/lib/swipl/library/prolog_clause.pl +1104 -0
  466. package/lib/swipl/library/prolog_code.pl +416 -0
  467. package/lib/swipl/library/prolog_codewalk.pl +1248 -0
  468. package/lib/swipl/library/prolog_colour.pl +3301 -0
  469. package/lib/swipl/library/prolog_colour.qlf +0 -0
  470. package/lib/swipl/library/prolog_config.pl +154 -0
  471. package/lib/swipl/library/prolog_coverage.pl +1333 -0
  472. package/lib/swipl/library/prolog_debug.pl +404 -0
  473. package/lib/swipl/library/prolog_deps.pl +675 -0
  474. package/lib/swipl/library/prolog_evaluable.pl +234 -0
  475. package/lib/swipl/library/prolog_format.pl +219 -0
  476. package/lib/swipl/library/prolog_history.pl +161 -0
  477. package/lib/swipl/library/prolog_jiti.pl +333 -0
  478. package/lib/swipl/library/prolog_locale.pl +61 -0
  479. package/lib/swipl/library/prolog_metainference.pl +307 -0
  480. package/lib/swipl/library/prolog_pack.pl +3906 -0
  481. package/lib/swipl/library/prolog_profile.pl +346 -0
  482. package/lib/swipl/library/prolog_qlfmake.pl +533 -0
  483. package/lib/swipl/library/prolog_source.pl +1188 -0
  484. package/lib/swipl/library/prolog_stack.pl +794 -0
  485. package/lib/swipl/library/prolog_trace.pl +365 -0
  486. package/lib/swipl/library/prolog_versions.pl +347 -0
  487. package/lib/swipl/library/prolog_wrap.pl +164 -0
  488. package/lib/swipl/library/prolog_xref.pl +3090 -0
  489. package/lib/swipl/library/prolog_xref.qlf +0 -0
  490. package/lib/swipl/library/pure_input.pl +266 -0
  491. package/lib/swipl/library/qpforeign.pl +695 -0
  492. package/lib/swipl/library/qsave.pl +1516 -0
  493. package/lib/swipl/library/quasi_quotations.pl +300 -0
  494. package/lib/swipl/library/quintus.pl +437 -0
  495. package/lib/swipl/library/random.pl +459 -0
  496. package/lib/swipl/library/rbtrees.pl +1153 -0
  497. package/lib/swipl/library/readln.pl +256 -0
  498. package/lib/swipl/library/readutil.pl +304 -0
  499. package/lib/swipl/library/record.pl +544 -0
  500. package/lib/swipl/library/rwlocks.pl +172 -0
  501. package/lib/swipl/library/sandbox.pl +1384 -0
  502. package/lib/swipl/library/semweb/dc.rdfs +198 -0
  503. package/lib/swipl/library/semweb/eor.rdfs +95 -0
  504. package/lib/swipl/library/semweb/owl.owl +287 -0
  505. package/lib/swipl/library/semweb/rdf_library.ttl +90 -0
  506. package/lib/swipl/library/semweb/rdfs.rdfs +251 -0
  507. package/lib/swipl/library/settings.pl +755 -0
  508. package/lib/swipl/library/shell.pl +462 -0
  509. package/lib/swipl/library/shlib.pl +670 -0
  510. package/lib/swipl/library/solution_sequences.pl +439 -0
  511. package/lib/swipl/library/sort.pl +119 -0
  512. package/lib/swipl/library/statistics.pl +541 -0
  513. package/lib/swipl/library/streams.pl +118 -0
  514. package/lib/swipl/library/strings.pl +469 -0
  515. package/lib/swipl/library/system.pl +95 -0
  516. package/lib/swipl/library/tables.pl +381 -0
  517. package/lib/swipl/library/tableutil.pl +771 -0
  518. package/lib/swipl/library/tabling.pl +42 -0
  519. package/lib/swipl/library/terms.pl +457 -0
  520. package/lib/swipl/library/theme/auto.pl +61 -0
  521. package/lib/swipl/library/theme/dark.pl +455 -0
  522. package/lib/swipl/library/theme/light.pl +45 -0
  523. package/lib/swipl/library/thread.pl +810 -0
  524. package/lib/swipl/library/thread_pool.pl +508 -0
  525. package/lib/swipl/library/threadutil.pl +574 -0
  526. package/lib/swipl/library/tty.pl +316 -0
  527. package/lib/swipl/library/ugraphs.pl +644 -0
  528. package/lib/swipl/library/unicode/INDEX.pl +6 -0
  529. package/lib/swipl/library/unicode/blocks.pl +414 -0
  530. package/lib/swipl/library/url.pl +1129 -0
  531. package/lib/swipl/library/utf8.pl +145 -0
  532. package/lib/swipl/library/varnumbers.pl +221 -0
  533. package/lib/swipl/library/vm.pl +251 -0
  534. package/lib/swipl/library/wfs.pl +205 -0
  535. package/lib/swipl/library/when.pl +263 -0
  536. package/lib/swipl/library/writef.pl +278 -0
  537. package/lib/swipl/library/www_browser.pl +251 -0
  538. package/lib/swipl/library/yall.pl +574 -0
  539. package/lib/swipl/library/zip.pl +211 -0
  540. package/lib/swipl/swipl.home +1 -0
  541. package/lib/vendor/libcrypto.so.3 +0 -0
  542. package/lib/vendor/libpcre2-8.so.0 +0 -0
  543. package/lib/vendor/libssl.so.3 +0 -0
  544. package/lib/vendor/libz.so.1 +0 -0
  545. package/licenses/OpenSSL-LICENSE.txt +177 -0
  546. package/licenses/PCRE2-COPYING +5 -0
  547. package/licenses/README.md +12 -0
  548. package/licenses/SWI-Prolog-LICENSE +41 -0
  549. package/licenses/zlib-LICENSE +22 -0
  550. package/package.json +27 -0
@@ -0,0 +1,1181 @@
1
+ /* Part of SWI-Prolog
2
+
3
+ Author: Jan Wielemaker
4
+ E-mail: J.Wielemaker@vu.nl
5
+ WWW: http://www.swi-prolog.org
6
+ Copyright (c) 2002-2024, University of Amsterdam
7
+ VU University Amsterdam
8
+ CWI, Amsterdam
9
+ SWI-Prolog Solutions b.v.
10
+ All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions
14
+ are met:
15
+
16
+ 1. Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+
19
+ 2. Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in
21
+ the documentation and/or other materials provided with the
22
+ distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
+ POSSIBILITY OF SUCH DAMAGE.
36
+ */
37
+
38
+ :- module(thread_httpd,
39
+ [ http_current_server/2, % ?:Goal, ?Port
40
+ http_server_property/2, % ?Port, ?Property
41
+ http_server/2, % :Goal, +Options
42
+ http_workers/2, % +Port, ?WorkerCount
43
+ http_add_worker/2, % +Port, +Options
44
+ http_current_worker/2, % ?Port, ?ThreadID
45
+ http_stop_server/2, % +Port, +Options
46
+ http_spawn/2, % :Goal, +Options
47
+
48
+ http_requeue/1, % +Request
49
+ http_close_connection/1, % +Request
50
+ http_enough_workers/3 % +Queue, +Why, +Peer
51
+ ]).
52
+ :- use_module(library(debug)).
53
+ :- use_module(library(error)).
54
+ :- use_module(library(option)).
55
+ :- use_module(library(socket)).
56
+ :- use_module(library(thread_pool)).
57
+ :- use_module(library(gensym)).
58
+ :- use_module(http_wrapper).
59
+ :- use_module(http_path).
60
+ :- use_module(http_stream).
61
+
62
+ :- autoload(library(uri), [uri_resolve/3]).
63
+ :- autoload(library(aggregate), [aggregate_all/3]).
64
+
65
+ :- predicate_options(http_server/2, 2,
66
+ [ port(any),
67
+ unix_socket(atom),
68
+ entry_page(atom),
69
+ tcp_socket(any),
70
+ workers(positive_integer),
71
+ timeout(number),
72
+ keep_alive_timeout(number),
73
+ silent(boolean),
74
+ ssl(list(any)), % if http/http_ssl_plugin is loaded
75
+ pass_to(system:thread_create/3, 3)
76
+ ]).
77
+ :- predicate_options(http_spawn/2, 2,
78
+ [ pool(atom),
79
+ pass_to(system:thread_create/3, 3),
80
+ pass_to(thread_pool:thread_create_in_pool/4, 4)
81
+ ]).
82
+ :- predicate_options(http_add_worker/2, 2,
83
+ [ timeout(number),
84
+ keep_alive_timeout(number),
85
+ max_idle_time(number),
86
+ pass_to(system:thread_create/3, 3)
87
+ ]).
88
+
89
+ /** <module> Threaded HTTP server
90
+
91
+ Most code doesn't need to use this directly; instead use
92
+ library(http/http_server), which combines this library with the
93
+ typical HTTP libraries that most servers need.
94
+
95
+ This library defines the HTTP server frontend of choice for SWI-Prolog.
96
+ It is based on the multi-threading capabilities of SWI-Prolog and thus
97
+ exploits multiple cores to serve requests concurrently. The server
98
+ scales well and can cooperate with library(thread_pool) to control the
99
+ number of concurrent requests of a given type. For example, it can be
100
+ configured to handle 200 file download requests concurrently, 2 requests
101
+ that potentially uses a lot of memory and 8 requests that use a lot of
102
+ CPU resources.
103
+
104
+ On Unix systems, this library can be combined with
105
+ library(http/http_unix_daemon) to realise a proper Unix service process
106
+ that creates a web server at port 80, runs under a specific account,
107
+ optionally detaches from the controlling terminal, etc.
108
+
109
+ Combined with library(http/http_ssl_plugin) from the SSL package, this
110
+ library can be used to create an HTTPS server. See
111
+ <plbase>/doc/packages/examples/ssl/https for an example server using a
112
+ self-signed SSL certificate.
113
+ */
114
+
115
+ :- meta_predicate
116
+ http_server(1, :),
117
+ http_current_server(1, ?),
118
+ http_spawn(0, +).
119
+
120
+ :- dynamic
121
+ current_server/6, % Port, Goal, Thread, Queue, Scheme, StartTime
122
+ queue_worker/2, % Queue, ThreadID
123
+ queue_options/2. % Queue, Options
124
+
125
+ :- multifile
126
+ make_socket_hook/3,
127
+ accept_hook/2,
128
+ close_hook/1,
129
+ open_client_hook/6,
130
+ discard_client_hook/1,
131
+ http:create_pool/1,
132
+ http:schedule_workers/1.
133
+
134
+ :- meta_predicate
135
+ thread_repeat_wait(0).
136
+
137
+ %! http_server(:Goal, :Options) is det.
138
+ %
139
+ % Create a server at Port that calls Goal for each parsed request.
140
+ % Options provide a list of options. Defined options are
141
+ %
142
+ % * port(?Address)
143
+ % Port to bind to. Address is either a port or a term
144
+ % Host:Port. The port may be a variable, causing the system
145
+ % to select a free port. See tcp_bind/2.
146
+ %
147
+ % * unix_socket(+Path)
148
+ % Instead of binding to a TCP port, bind to a _Unix Domain
149
+ % Socket_ at Path.
150
+ %
151
+ % * entry_page(+URI)
152
+ % Affects the message printed while the server is started.
153
+ % Interpreted as a URI relative to the server root.
154
+ %
155
+ % * tcp_socket(+Socket)
156
+ % If provided, use this socket instead of the creating one and
157
+ % binding it to an address. The socket must be bound to an
158
+ % address. Note that this also allows binding an HTTP server to
159
+ % a Unix domain socket (``AF_UNIX``). See socket_create/2.
160
+ %
161
+ % * workers(+Count)
162
+ % Determine the number of worker threads. Default is 5. This
163
+ % is fine for small scale usage. Public servers typically need
164
+ % a higher number.
165
+ %
166
+ % * timeout(+Seconds)
167
+ % Maximum time of inactivity trying to read the request after a
168
+ % connection has been opened. Default is 60 seconds. See
169
+ % set_stream/1 using the _timeout_ option.
170
+ %
171
+ % * keep_alive_timeout(+Seconds)
172
+ % Time to keep `Keep alive' connections alive. Default is
173
+ % 2 seconds.
174
+ %
175
+ % * stack_limit(+Bytes)
176
+ % Stack limit to use for the workers. The default is inherited
177
+ % from the `main` thread.
178
+ % If you need to control resource usage you may consider the
179
+ % `spawn` option of http_handler/3 and library(thread_pool).
180
+ %
181
+ % * silent(Bool)
182
+ % If `true` (default `false`), do not print an informational
183
+ % message that the server was started.
184
+ %
185
+ % A typical initialization for an HTTP server that uses
186
+ % http_dispatch/1 to relay requests to predicates is:
187
+ %
188
+ % ==
189
+ % :- use_module(library(http/thread_httpd)).
190
+ % :- use_module(library(http/http_dispatch)).
191
+ %
192
+ % start_server(Port) :-
193
+ % http_server(http_dispatch, [port(Port)]).
194
+ % ==
195
+ %
196
+ % Note that multiple servers can coexist in the same Prolog
197
+ % process. A notable application of this is to have both an HTTP
198
+ % and HTTPS server, where the HTTP server redirects to the HTTPS
199
+ % server for handling sensitive requests.
200
+
201
+ http_server(Goal, M:Options0) :-
202
+ server_address(Address, Options0),
203
+ !,
204
+ make_socket(Address, M:Options0, Options),
205
+ create_workers(Options),
206
+ create_server(Goal, Address, Options),
207
+ ( option(silent(true), Options0)
208
+ -> true
209
+ ; print_message(informational,
210
+ httpd_started_server(Address, Options0))
211
+ ).
212
+ http_server(_Goal, _:Options0) :-
213
+ existence_error(server_address, Options0).
214
+
215
+ server_address(Address, Options) :-
216
+ ( option(port(Port), Options)
217
+ -> Address = Port
218
+ ; option(unix_socket(Path), Options)
219
+ -> Address = unix_socket(Path)
220
+ ).
221
+
222
+ address_port(_IFace:Port, Port) :- !.
223
+ address_port(unix_socket(Path), Path) :- !.
224
+ address_port(Address, Address) :- !.
225
+
226
+ tcp_address(Port) :-
227
+ var(Port),
228
+ !.
229
+ tcp_address(Port) :-
230
+ integer(Port),
231
+ !.
232
+ tcp_address(_Iface:_Port).
233
+
234
+ address_domain(localhost:_Port, Domain) =>
235
+ Domain = inet.
236
+ address_domain(Iface:_Port, Domain) =>
237
+ ( catch(ip_name(IP, Iface), error(_,_), fail),
238
+ functor(IP, ip, 8)
239
+ -> Domain = inet6
240
+ ; Domain = inet
241
+ ).
242
+ address_domain(_, Domain) =>
243
+ Domain = inet.
244
+
245
+
246
+ %! make_socket(+Address, :OptionsIn, -OptionsOut) is det.
247
+ %
248
+ % Create the HTTP server socket and worker pool queue. OptionsOut
249
+ % is guaranteed to hold the option queue(QueueId).
250
+ %
251
+ % @arg OptionsIn is qualified to allow passing the
252
+ % module-sensitive ssl option argument.
253
+
254
+ make_socket(Address, M:Options0, Options) :-
255
+ tcp_address(Address),
256
+ make_socket_hook(Address, M:Options0, Options),
257
+ !.
258
+ make_socket(Address, _:Options0, Options) :-
259
+ option(tcp_socket(_), Options0),
260
+ !,
261
+ make_addr_atom('httpd', Address, Queue),
262
+ Options = [ queue(Queue)
263
+ | Options0
264
+ ].
265
+ make_socket(Address, _:Options0, Options) :-
266
+ tcp_address(Address),
267
+ !,
268
+ address_domain(Address, Domain),
269
+ socket_create(Socket, [domain(Domain)]),
270
+ tcp_setopt(Socket, reuseaddr),
271
+ tcp_bind(Socket, Address),
272
+ tcp_listen(Socket, 64),
273
+ make_addr_atom('httpd', Address, Queue),
274
+ Options = [ queue(Queue),
275
+ tcp_socket(Socket)
276
+ | Options0
277
+ ].
278
+ :- if(current_predicate(unix_domain_socket/1)).
279
+ make_socket(Address, _:Options0, Options) :-
280
+ Address = unix_socket(Path),
281
+ !,
282
+ unix_domain_socket(Socket),
283
+ tcp_bind(Socket, Path),
284
+ tcp_listen(Socket, 64),
285
+ make_addr_atom('httpd', Address, Queue),
286
+ Options = [ queue(Queue),
287
+ tcp_socket(Socket)
288
+ | Options0
289
+ ].
290
+ :- endif.
291
+
292
+ %! make_addr_atom(+Scheme, +Address, -Atom) is det.
293
+ %
294
+ % Create an atom that identifies the server's queue and thread
295
+ % resources.
296
+
297
+ make_addr_atom(Scheme, Address, Atom) :-
298
+ phrase(address_parts(Address), Parts),
299
+ atomic_list_concat([Scheme,@|Parts], Atom).
300
+
301
+ address_parts(Var) -->
302
+ { var(Var),
303
+ !,
304
+ instantiation_error(Var)
305
+ }.
306
+ address_parts(Atomic) -->
307
+ { atomic(Atomic) },
308
+ !,
309
+ [Atomic].
310
+ address_parts(Host:Port) -->
311
+ !,
312
+ address_parts(Host), [:], address_parts(Port).
313
+ address_parts(ip(A,B,C,D)) -->
314
+ !,
315
+ [ A, '.', B, '.', C, '.', D ].
316
+ address_parts(unix_socket(Path)) -->
317
+ [Path].
318
+ address_parts(Address) -->
319
+ { domain_error(http_server_address, Address) }.
320
+
321
+
322
+ %! create_server(:Goal, +Address, +Options) is det.
323
+ %
324
+ % Create the main server thread that runs accept_server/2 to
325
+ % listen to new requests.
326
+
327
+ create_server(Goal, Address, Options) :-
328
+ get_time(StartTime),
329
+ memberchk(queue(Queue), Options),
330
+ scheme(Scheme, Options),
331
+ autoload_https(Scheme),
332
+ address_port(Address, Port),
333
+ make_addr_atom(Scheme, Port, Alias),
334
+ thread_self(Initiator),
335
+ thread_create(accept_server(Goal, Initiator, Options), _,
336
+ [ alias(Alias),
337
+ class(service)
338
+ ]),
339
+ thread_get_message(server_started),
340
+ assert(current_server(Port, Goal, Alias, Queue, Scheme, StartTime)).
341
+
342
+ scheme(Scheme, Options) :-
343
+ option(scheme(Scheme), Options),
344
+ !.
345
+ scheme(Scheme, Options) :-
346
+ ( option(ssl(_), Options)
347
+ ; option(ssl_instance(_), Options)
348
+ ),
349
+ !,
350
+ Scheme = https.
351
+ scheme(http, _).
352
+
353
+ autoload_https(https) :-
354
+ \+ clause(accept_hook(_Goal, _Options), _),
355
+ exists_source(library(http/http_ssl_plugin)),
356
+ !,
357
+ use_module(library(http/http_ssl_plugin)).
358
+ autoload_https(_).
359
+
360
+ %! http_current_server(:Goal, ?Port) is nondet.
361
+ %
362
+ % True if Goal is the goal of a server at Port.
363
+ %
364
+ % @deprecated Use http_server_property(Port, goal(Goal))
365
+
366
+ http_current_server(Goal, Port) :-
367
+ current_server(Port, Goal, _, _, _, _).
368
+
369
+
370
+ %! http_server_property(?Port, ?Property) is nondet.
371
+ %
372
+ % True if Property is a property of the HTTP server running at
373
+ % Port. Defined properties are:
374
+ %
375
+ % * goal(:Goal)
376
+ % Goal used to start the server. This is often
377
+ % http_dispatch/1.
378
+ % * scheme(-Scheme)
379
+ % Scheme is one of `http` or `https`.
380
+ % * start_time(?Time)
381
+ % Time-stamp when the server was created.
382
+
383
+ http_server_property(_:Port, Property) :-
384
+ integer(Port),
385
+ !,
386
+ server_property(Property, Port).
387
+ http_server_property(Port, Property) :-
388
+ server_property(Property, Port).
389
+
390
+ server_property(goal(Goal), Port) :-
391
+ current_server(Port, Goal, _, _, _, _).
392
+ server_property(scheme(Scheme), Port) :-
393
+ current_server(Port, _, _, _, Scheme, _).
394
+ server_property(start_time(Time), Port) :-
395
+ current_server(Port, _, _, _, _, Time).
396
+
397
+
398
+ %! http_workers(?Port, -Workers) is nondet.
399
+ %! http_workers(+Port, +Workers:int) is det.
400
+ %
401
+ % Query or set the number of workers for the server at this port. The
402
+ % number of workers is dynamically modified. Setting it to 1 (one) can
403
+ % be used to profile the worker using tprofile/1.
404
+ %
405
+ % @see library(http/http_dyn_workers) implements dynamic management of
406
+ % the worker pool depending on usage.
407
+
408
+ http_workers(Port, Workers) :-
409
+ integer(Workers),
410
+ !,
411
+ must_be(ground, Port),
412
+ ( current_server(Port, _, _, Queue, _, _)
413
+ -> resize_pool(Queue, Workers)
414
+ ; existence_error(http_server, Port)
415
+ ).
416
+ http_workers(Port, Workers) :-
417
+ current_server(Port, _, _, Queue, _, _),
418
+ aggregate_all(count, queue_worker(Queue, _Worker), Workers).
419
+
420
+
421
+ %! http_add_worker(+Port, +Options) is det.
422
+ %
423
+ % Add a new worker to the HTTP server for port Port. Options
424
+ % overrule the default queue options. The following additional
425
+ % options are processed:
426
+ %
427
+ % - max_idle_time(+Seconds)
428
+ % The created worker will automatically terminate if there is
429
+ % no new work within Seconds.
430
+
431
+ http_add_worker(Port, Options) :-
432
+ must_be(ground, Port),
433
+ current_server(Port, _, _, Queue, _, _),
434
+ !,
435
+ queue_options(Queue, QueueOptions),
436
+ merge_options(Options, QueueOptions, WorkerOptions),
437
+ atom_concat(Queue, '_', AliasBase),
438
+ create_workers(1, 1, Queue, AliasBase, WorkerOptions).
439
+ http_add_worker(Port, _) :-
440
+ existence_error(http_server, Port).
441
+
442
+
443
+ %! http_current_worker(?Port, ?ThreadID) is nondet.
444
+ %
445
+ % True if ThreadID is the identifier of a Prolog thread serving
446
+ % Port. This predicate is motivated to allow for the use of
447
+ % arbitrary interaction with the worker thread for development and
448
+ % statistics.
449
+
450
+ http_current_worker(Port, ThreadID) :-
451
+ current_server(Port, _, _, Queue, _, _),
452
+ queue_worker(Queue, ThreadID).
453
+
454
+
455
+ %! accept_server(:Goal, +Initiator, +Options)
456
+ %
457
+ % The goal of a small server-thread accepting new requests and
458
+ % posting them to the queue of workers.
459
+
460
+ accept_server(Goal, Initiator, Options) :-
461
+ Ex = http_stop(Stopper),
462
+ catch(accept_server2(Goal, Initiator, Options), Ex, true),
463
+ thread_self(Thread),
464
+ debug(http(stop), '[~p]: accept server received ~p', [Thread, Ex]),
465
+ retract(current_server(_Port, _, Thread, Queue, _Scheme, _StartTime)),
466
+ close_pending_accepts(Queue),
467
+ close_server_socket(Options),
468
+ thread_send_message(Stopper, http_stopped).
469
+
470
+ accept_server2(Goal, Initiator, Options) :-
471
+ thread_send_message(Initiator, server_started),
472
+ repeat,
473
+ ( catch(accept_server3(Goal, Options), E, true)
474
+ -> ( var(E)
475
+ -> fail
476
+ ; accept_rethrow_error(E)
477
+ -> throw(E)
478
+ ; print_message(error, E),
479
+ fail
480
+ )
481
+ ; print_message(error, % internal error
482
+ goal_failed(accept_server3(Goal, Options))),
483
+ fail
484
+ ).
485
+
486
+ accept_server3(Goal, Options) :-
487
+ accept_hook(Goal, Options),
488
+ !.
489
+ accept_server3(Goal, Options) :-
490
+ memberchk(tcp_socket(Socket), Options),
491
+ memberchk(queue(Queue), Options),
492
+ debug(http(connection), 'Waiting for connection', []),
493
+ tcp_accept(Socket, Client, Peer),
494
+ sig_atomic(send_to_worker(Queue, Client, Goal, Peer)),
495
+ http_enough_workers(Queue, accept, Peer).
496
+
497
+ send_to_worker(Queue, Client, Goal, Peer) :-
498
+ debug(http(connection), 'New HTTP connection from ~p', [Peer]),
499
+ thread_send_message(Queue, tcp_client(Client, Goal, Peer)).
500
+
501
+ accept_rethrow_error(http_stop(_)).
502
+
503
+ %! close_server_socket(+Options)
504
+ %
505
+ % Close the server socket.
506
+
507
+ close_server_socket(Options) :-
508
+ close_hook(Options),
509
+ !.
510
+ close_server_socket(Options) :-
511
+ memberchk(tcp_socket(Socket), Options),
512
+ !,
513
+ tcp_close_socket(Socket).
514
+
515
+ %! close_pending_accepts(+Queue)
516
+
517
+ close_pending_accepts(Queue) :-
518
+ ( thread_get_message(Queue, Msg, [timeout(0)])
519
+ -> close_client(Msg),
520
+ close_pending_accepts(Queue)
521
+ ; true
522
+ ).
523
+
524
+ close_client(tcp_client(Client, _Goal, _0Peer)) =>
525
+ debug(http(stop), 'Closing connection from ~p during shut-down', [_0Peer]),
526
+ tcp_close_socket(Client).
527
+ close_client(Msg) =>
528
+ ( discard_client_hook(Msg)
529
+ -> true
530
+ ; print_message(warning, http_close_client(Msg))
531
+ ).
532
+
533
+
534
+ %! http_stop_server(+Port, +Options)
535
+ %
536
+ % Stop the indicated HTTP server gracefully. First stops all
537
+ % workers, then stops the server.
538
+ %
539
+ % @tbd Realise non-graceful stop
540
+
541
+ http_stop_server(Host:Port, Options) :- % e.g., localhost:4000
542
+ ground(Host),
543
+ !,
544
+ http_stop_server(Port, Options).
545
+ http_stop_server(Port, _Options) :-
546
+ http_workers(Port, 0), % checks Port is ground
547
+ current_server(Port, _, Thread, Queue, _Scheme, _Start),
548
+ retractall(queue_options(Queue, _)),
549
+ debug(http(stop), 'Signalling HTTP server thread ~p to stop', [Thread]),
550
+ thread_self(Stopper),
551
+ thread_signal(Thread, throw(http_stop(Stopper))),
552
+ ( thread_get_message(Stopper, http_stopped, [timeout(0.1)])
553
+ -> true
554
+ ; catch(connect(localhost:Port), _, true)
555
+ ),
556
+ thread_join(Thread, _0Status),
557
+ debug(http(stop), 'Joined HTTP server thread ~p (~p)', [Thread, _0Status]),
558
+ message_queue_destroy(Queue).
559
+
560
+ connect(Address) :-
561
+ setup_call_cleanup(
562
+ tcp_socket(Socket),
563
+ tcp_connect(Socket, Address),
564
+ tcp_close_socket(Socket)).
565
+
566
+ %! http_enough_workers(+Queue, +Why, +Peer) is det.
567
+ %
568
+ % Check that we have enough workers in our queue. If not, call the
569
+ % hook http:schedule_workers/1 to extend the worker pool. This
570
+ % predicate can be used by accept_hook/2.
571
+
572
+ http_enough_workers(Queue, _Why, _Peer) :-
573
+ message_queue_property(Queue, waiting(_0)),
574
+ !,
575
+ debug(http(scheduler), '~D waiting for work; ok', [_0]).
576
+ http_enough_workers(Queue, Why, Peer) :-
577
+ message_queue_property(Queue, size(Size)),
578
+ ( enough(Size, Why)
579
+ -> debug(http(scheduler), '~D in queue; ok', [Size])
580
+ ; current_server(Port, _, _, Queue, _, _),
581
+ Data = _{ port:Port,
582
+ reason:Why,
583
+ peer:Peer,
584
+ waiting:Size,
585
+ queue:Queue
586
+ },
587
+ debug(http(scheduler), 'Asking to reschedule: ~p', [Data]),
588
+ catch(http:schedule_workers(Data),
589
+ Error,
590
+ print_message(error, Error))
591
+ -> true
592
+ ; true
593
+ ).
594
+
595
+ enough(0, _).
596
+ enough(1, keep_alive). % I will be ready myself
597
+
598
+
599
+ %! http:schedule_workers(+Data:dict) is semidet.
600
+ %
601
+ % Hook called if a new connection or a keep-alive connection
602
+ % cannot be scheduled _immediately_ to a worker. Dict contains the
603
+ % following keys:
604
+ %
605
+ % - port:Port
606
+ % Port number that identifies the server.
607
+ % - reason:Reason
608
+ % One of =accept= for a new connection or =keep_alive= if a
609
+ % worker tries to reschedule itself.
610
+ % - peer:Peer
611
+ % Identify the other end of the connection
612
+ % - waiting:Size
613
+ % Number of messages waiting in the queue.
614
+ % - queue:Queue
615
+ % Message queue used to dispatch accepted messages.
616
+ %
617
+ % Note that, when called with `reason:accept`, we are called in
618
+ % the time critical main accept loop. An implementation of this
619
+ % hook shall typically send the event to thread dedicated to
620
+ % dynamic worker-pool management.
621
+ %
622
+ % @see http_add_worker/2 may be used to create (temporary) extra
623
+ % workers.
624
+
625
+
626
+ /*******************************
627
+ * WORKER QUEUE OPERATIONS *
628
+ *******************************/
629
+
630
+ %! create_workers(+Options)
631
+ %
632
+ % Create the pool of HTTP worker-threads. Each worker has the
633
+ % alias http_worker_N.
634
+
635
+ create_workers(Options) :-
636
+ option(workers(N), Options, 5),
637
+ option(queue(Queue), Options),
638
+ catch(message_queue_create(Queue), _, true),
639
+ atom_concat(Queue, '_', AliasBase),
640
+ create_workers(1, N, Queue, AliasBase, Options),
641
+ assert(queue_options(Queue, Options)).
642
+
643
+ create_workers(I, N, _, _, _) :-
644
+ I > N,
645
+ !.
646
+ create_workers(I, N, Queue, AliasBase, Options) :-
647
+ gensym(AliasBase, Alias),
648
+ thread_create(http_worker(Options), Id,
649
+ [ alias(Alias),
650
+ class(http)
651
+ | Options
652
+ ]),
653
+ assertz(queue_worker(Queue, Id)),
654
+ I2 is I + 1,
655
+ create_workers(I2, N, Queue, AliasBase, Options).
656
+
657
+
658
+ %! resize_pool(+Queue, +Workers) is det.
659
+ %
660
+ % Create or destroy workers. If workers are destroyed, the call
661
+ % waits until the desired number of waiters is reached.
662
+
663
+ resize_pool(Queue, Size) :-
664
+ findall(W, queue_worker(Queue, W), Workers),
665
+ length(Workers, Now),
666
+ ( Now < Size
667
+ -> queue_options(Queue, Options),
668
+ atom_concat(Queue, '_', AliasBase),
669
+ I0 is Now+1,
670
+ create_workers(I0, Size, Queue, AliasBase, Options)
671
+ ; Now == Size
672
+ -> true
673
+ ; Now > Size
674
+ -> Excess is Now - Size,
675
+ thread_self(Me),
676
+ forall(between(1, Excess, _), thread_send_message(Queue, quit(Me))),
677
+ forall(between(1, Excess, _), thread_get_message(quitted(_)))
678
+ ).
679
+
680
+
681
+ %! http_worker(+Options)
682
+ %
683
+ % Run HTTP worker main loop. Workers simply wait until they are
684
+ % passed an accepted socket to process a client.
685
+ %
686
+ % If the message quit(Sender) is read from the queue, the worker
687
+ % stops.
688
+
689
+ http_worker(Options) :-
690
+ debug(http(scheduler), 'New worker', []),
691
+ prolog_listen(this_thread_exit, done_worker),
692
+ option(queue(Queue), Options),
693
+ option(max_idle_time(MaxIdle), Options, infinite),
694
+ thread_repeat_wait(get_work(Queue, Message, MaxIdle)),
695
+ debug(http(worker), 'Waiting for a job ...', []),
696
+ debug(http(worker), 'Got job ~p', [Message]),
697
+ ( Message = quit(Sender)
698
+ -> !,
699
+ thread_self(Self),
700
+ thread_detach(Self),
701
+ ( Sender == idle
702
+ -> true
703
+ ; retract(queue_worker(Queue, Self)),
704
+ thread_send_message(Sender, quitted(Self))
705
+ )
706
+ ; open_client(Message, Queue, Goal, In, Out,
707
+ Options, ClientOptions),
708
+ ( catch(http_process(Goal, In, Out, ClientOptions),
709
+ Error, true)
710
+ -> true
711
+ ; Error = goal_failed(http_process/4)
712
+ ),
713
+ debug_reset_from_class, % Restore debug mode after user nodebug
714
+ ( var(Error)
715
+ -> fail
716
+ ; current_message_level(Error, Level),
717
+ print_message(Level, Error),
718
+ memberchk(peer(Peer), ClientOptions),
719
+ close_connection(Peer, In, Out),
720
+ fail
721
+ )
722
+ ).
723
+
724
+ get_work(Queue, Message, infinite) :-
725
+ !,
726
+ thread_get_message(Queue, Message).
727
+ get_work(Queue, Message, MaxIdle) :-
728
+ ( thread_get_message(Queue, Message, [timeout(MaxIdle)])
729
+ -> true
730
+ ; Message = quit(idle)
731
+ ).
732
+
733
+
734
+ %! open_client(+Message, +Queue, -Goal, -In, -Out,
735
+ %! +Options, -ClientOptions) is semidet.
736
+ %
737
+ % Opens the connection to the client in a worker from the message
738
+ % sent to the queue by accept_server/2.
739
+
740
+ open_client(requeue(In, Out, Goal, ClOpts),
741
+ _, Goal, In, Out, Opts, ClOpts) :-
742
+ !,
743
+ memberchk(peer(Peer), ClOpts),
744
+ option(keep_alive_timeout(KeepAliveTMO), Opts, 2),
745
+ check_keep_alive_connection(In, KeepAliveTMO, Peer, In, Out).
746
+ open_client(Message, Queue, Goal, In, Out, Opts,
747
+ [ pool(client(Queue, Goal, In, Out)),
748
+ timeout(Timeout)
749
+ | Options
750
+ ]) :-
751
+ catch(open_client(Message, Goal, In, Out, Options, Opts),
752
+ E, report_error(E)),
753
+ option(timeout(Timeout), Opts, 60),
754
+ ( debugging(http(connection))
755
+ -> memberchk(peer(Peer), Options),
756
+ debug(http(connection), 'Opened connection from ~p', [Peer])
757
+ ; true
758
+ ).
759
+
760
+
761
+ %! open_client(+Message, +Goal, -In, -Out,
762
+ %! -ClientOptions, +Options) is det.
763
+
764
+ open_client(Message, Goal, In, Out, ClientOptions, Options) :-
765
+ open_client_hook(Message, Goal, In, Out, ClientOptions, Options),
766
+ !.
767
+ open_client(tcp_client(Socket, Goal, Peer), Goal, In, Out,
768
+ [ peer(Peer),
769
+ protocol(http)
770
+ ], _) :-
771
+ tcp_open_socket(Socket, In, Out).
772
+
773
+ report_error(E) :-
774
+ print_message(error, E),
775
+ fail.
776
+
777
+
778
+ %! check_keep_alive_connection(+In, +TimeOut, +Peer, +In, +Out) is semidet.
779
+ %
780
+ % Wait for the client for at most TimeOut seconds. Succeed if the
781
+ % client starts a new request within this time. Otherwise close
782
+ % the connection and fail.
783
+
784
+ check_keep_alive_connection(In, TMO, Peer, In, Out) :-
785
+ stream_property(In, timeout(Old)),
786
+ set_stream(In, timeout(TMO)),
787
+ debug(http(keep_alive), 'Waiting for keep-alive ...', []),
788
+ catch(peek_code(In, Code), E, true),
789
+ ( var(E), % no exception
790
+ Code \== -1 % no end-of-file
791
+ -> set_stream(In, timeout(Old)),
792
+ debug(http(keep_alive), '\tre-using keep-alive connection', [])
793
+ ; ( Code == -1
794
+ -> debug(http(keep_alive), '\tRemote closed keep-alive connection', [])
795
+ ; debug(http(keep_alive), '\tTimeout on keep-alive connection', [])
796
+ ),
797
+ close_connection(Peer, In, Out),
798
+ fail
799
+ ).
800
+
801
+
802
+ %! done_worker
803
+ %
804
+ % Called when worker is terminated due to http_workers/2 or a
805
+ % (debugging) exception. In the latter case, recreate_worker/2
806
+ % creates a new worker.
807
+
808
+ done_worker :-
809
+ thread_self(Self),
810
+ thread_detach(Self),
811
+ retract(queue_worker(Queue, Self)),
812
+ thread_property(Self, status(Status)),
813
+ !,
814
+ ( catch(recreate_worker(Status, Queue), _, fail)
815
+ -> print_message(informational,
816
+ httpd_restarted_worker(Self))
817
+ ; done_status_message_level(Status, Level),
818
+ print_message(Level,
819
+ httpd_stopped_worker(Self, Status))
820
+ ).
821
+ done_worker :- % received quit(Sender)
822
+ thread_self(Self),
823
+ thread_property(Self, status(Status)),
824
+ done_status_message_level(Status, Level),
825
+ print_message(Level,
826
+ httpd_stopped_worker(Self, Status)).
827
+
828
+ done_status_message_level(true, silent) :- !.
829
+ done_status_message_level(exception('$aborted'), silent) :- !.
830
+ done_status_message_level(exception(unwind(abort)), silent) :- !.
831
+ done_status_message_level(exception(unwind(halt(_))), silent) :- !.
832
+ done_status_message_level(_, informational).
833
+
834
+
835
+ %! recreate_worker(+Status, +Queue) is semidet.
836
+ %
837
+ % Deal with the possibility that threads are, during development,
838
+ % killed with abort/0. We recreate the worker to avoid that eventually
839
+ % we run out of workers. If we are aborted due to a halt/0 call,
840
+ % thread_create/3 will raise a permission error.
841
+ %
842
+ % The first clause deals with the possibility that we cannot write to
843
+ % `user_error`. This is possible when Prolog is started as a service
844
+ % using some service managers. Would be nice if we could write an
845
+ % error, but where?
846
+
847
+ recreate_worker(exception(error(io_error(write,user_error),_)), _Queue) :-
848
+ halt(2).
849
+ recreate_worker(exception(Error), Queue) :-
850
+ recreate_on_error(Error),
851
+ queue_options(Queue, Options),
852
+ atom_concat(Queue, '_', AliasBase),
853
+ create_workers(1, 1, Queue, AliasBase, Options).
854
+
855
+ recreate_on_error('$aborted').
856
+ recreate_on_error(unwind(abort)).
857
+ recreate_on_error(time_limit_exceeded).
858
+
859
+ %! thread_httpd:message_level(+Exception, -Level)
860
+ %
861
+ % Determine the message stream used for exceptions that may occur
862
+ % during server_loop/5. Being multifile, clauses can be added by the
863
+ % application to refine error handling. See also message_hook/3 for
864
+ % further programming error handling.
865
+
866
+ :- multifile
867
+ message_level/2.
868
+
869
+ message_level(error(io_error(read, _), _), silent).
870
+ message_level(error(socket_error(epipe,_), _), silent).
871
+ message_level(error(http_write_short(_Obj,_Written), _), silent).
872
+ message_level(error(timeout_error(read, _), _), informational).
873
+ message_level(keep_alive_timeout, silent).
874
+
875
+ current_message_level(Term, Level) :-
876
+ ( message_level(Term, Level)
877
+ -> true
878
+ ; Level = error
879
+ ).
880
+
881
+ %! read_remaining_request(+StartBody, +Request) is semidet.
882
+ %
883
+ % If our handler did not read the complete request we must read the
884
+ % remainder if we are dealing with a Keep-alive connection.
885
+
886
+ read_remaining_request(StartBody, Request) :-
887
+ memberchk(content_length(Len), Request),
888
+ !,
889
+ memberchk(pool(client(_Queue, _Goal, In, _Out)), Request),
890
+ byte_count(In, Here),
891
+ Left is StartBody+Len-Here,
892
+ read_incomplete(In, Left).
893
+ read_remaining_request(_, _Request).
894
+
895
+ read_incomplete(_, 0) :-
896
+ !.
897
+ read_incomplete(In, Left) :-
898
+ % Left < 1 000 000, % Optionally close anyway.
899
+ catch(setup_call_cleanup(
900
+ open_null_stream(Null),
901
+ copy_stream_data(In, Null, Left),
902
+ close(Null)),
903
+ error(_,_),
904
+ fail).
905
+
906
+ %! http_requeue(+Header)
907
+ %
908
+ % Re-queue a connection to the worker pool. This deals with
909
+ % processing additional requests on keep-alive connections.
910
+
911
+ http_requeue(Header) :-
912
+ requeue_header(Header, ClientOptions),
913
+ memberchk(pool(client(Queue, Goal, In, Out)), ClientOptions),
914
+ memberchk(peer(Peer), ClientOptions),
915
+ http_enough_workers(Queue, keep_alive, Peer),
916
+ thread_send_message(Queue, requeue(In, Out, Goal, ClientOptions)),
917
+ !.
918
+ http_requeue(Header) :-
919
+ debug(http(error), 'Re-queue failed: ~p', [Header]),
920
+ fail.
921
+
922
+ requeue_header([], []).
923
+ requeue_header([H|T0], [H|T]) :-
924
+ requeue_keep(H),
925
+ !,
926
+ requeue_header(T0, T).
927
+ requeue_header([_|T0], T) :-
928
+ requeue_header(T0, T).
929
+
930
+ requeue_keep(pool(_)).
931
+ requeue_keep(peer(_)).
932
+ requeue_keep(protocol(_)).
933
+
934
+
935
+ %! http_process(Message, Queue, +Options)
936
+ %
937
+ % Handle a single client message on the given stream.
938
+
939
+ http_process(Goal, In, Out, Options) :-
940
+ debug(http(server), 'Running server goal ~p on ~p -> ~p',
941
+ [Goal, In, Out]),
942
+ option(timeout(TMO), Options, 60),
943
+ set_stream(In, timeout(TMO)),
944
+ set_stream(Out, timeout(TMO)),
945
+ http_wrapper(Goal, In, Out, Connection,
946
+ [ request(Request),
947
+ byte_count(StartBody)
948
+ | Options
949
+ ]),
950
+ next(Connection, StartBody, Request).
951
+
952
+ next(Connection, StartBody, Request) :-
953
+ next_(Connection, StartBody, Request), !.
954
+ next(Connection, StartBody, Request) :-
955
+ print_message(warning, goal_failed(next(Connection,StartBody,Request))).
956
+
957
+ next_(switch_protocol(SwitchGoal, _SwitchOptions), _, Request) :-
958
+ !,
959
+ memberchk(pool(client(_Queue, _Goal, In, Out)), Request),
960
+ ( catch(call(SwitchGoal, In, Out), E,
961
+ ( print_message(error, E),
962
+ fail))
963
+ -> true
964
+ ; http_close_connection(Request)
965
+ ).
966
+ next_(spawned(ThreadId), _, _) :-
967
+ !,
968
+ debug(http(spawn), 'Handler spawned to thread ~w', [ThreadId]).
969
+ next_(Connection, StartBody, Request) :-
970
+ downcase_atom(Connection, 'keep-alive'),
971
+ read_remaining_request(StartBody, Request),
972
+ http_requeue(Request),
973
+ !.
974
+ next_(_, _, Request) :-
975
+ http_close_connection(Request).
976
+
977
+
978
+ %! http_close_connection(+Request)
979
+ %
980
+ % Close connection associated to Request. See also http_requeue/1.
981
+
982
+ http_close_connection(Request) :-
983
+ memberchk(pool(client(_Queue, _Goal, In, Out)), Request),
984
+ memberchk(peer(Peer), Request),
985
+ close_connection(Peer, In, Out).
986
+
987
+ %! close_connection(+Peer, +In, +Out)
988
+ %
989
+ % Closes the connection from the server to the client. Errors are
990
+ % currently silently ignored.
991
+
992
+ close_connection(Peer, In, Out) :-
993
+ debug(http(connection), 'Closing connection from ~p', [Peer]),
994
+ catch(close(In, [force(true)]), _, true),
995
+ catch(close(Out, [force(true)]), _, true).
996
+
997
+ %! http_spawn(:Goal, +Options) is det.
998
+ %
999
+ % Continue this connection on a new thread. A handler may call
1000
+ % http_spawn/2 to start a new thread that continues processing the
1001
+ % current request using Goal. The original thread returns to the
1002
+ % worker pool for processing new requests. Options are passed to
1003
+ % thread_create/3, except for:
1004
+ %
1005
+ % * pool(+Pool)
1006
+ % Interfaces to library(thread_pool), starting the thread
1007
+ % on the given pool.
1008
+ %
1009
+ % If a pool does not exist, this predicate calls the multifile
1010
+ % hook http:create_pool/1 to create it. If this predicate succeeds
1011
+ % the operation is retried.
1012
+
1013
+ http_spawn(Goal, Options) :-
1014
+ select_option(pool(Pool), Options, ThreadOptions),
1015
+ !,
1016
+ current_output(CGI),
1017
+ Error = error(Formal, _),
1018
+ catch(thread_create_in_pool(Pool,
1019
+ wrap_spawned(CGI, Goal), Id,
1020
+ [ detached(true),
1021
+ class(http)
1022
+ | ThreadOptions
1023
+ ]),
1024
+ Error,
1025
+ true),
1026
+ ( var(Formal)
1027
+ -> http_spawned(Id)
1028
+ ; Formal = resource_error(threads_in_pool(_))
1029
+ -> throw(http_reply(busy))
1030
+ ; Formal = existence_error(thread_pool, Pool),
1031
+ create_pool(Pool)
1032
+ -> http_spawn(Goal, Options)
1033
+ ; throw(Error)
1034
+ ).
1035
+ http_spawn(Goal, Options) :-
1036
+ current_output(CGI),
1037
+ thread_create(wrap_spawned(CGI, Goal), Id,
1038
+ [ detached(true),
1039
+ class(http)
1040
+ | Options
1041
+ ]),
1042
+ http_spawned(Id).
1043
+
1044
+ wrap_spawned(CGI, Goal) :-
1045
+ set_output(CGI),
1046
+ cgi_property(CGI, request(Request)),
1047
+ memberchk(input(Input), Request),
1048
+ byte_count(Input, StartBody),
1049
+ http_wrap_spawned(Goal, Request, Connection),
1050
+ next(Connection, StartBody, Request).
1051
+
1052
+ %! create_pool(+Pool)
1053
+ %
1054
+ % Lazy creation of worker-pools for the HTTP server. This
1055
+ % predicate calls the hook http:create_pool/1. If the hook fails
1056
+ % it creates a default pool of size 10. This should suffice most
1057
+ % typical usecases. Note that we get a permission error if the
1058
+ % pool is already created. We can ignore this.
1059
+
1060
+ create_pool(Pool) :-
1061
+ E = error(permission_error(create, thread_pool, Pool), _),
1062
+ catch(http:create_pool(Pool), E, true).
1063
+ create_pool(Pool) :-
1064
+ print_message(informational, httpd(created_pool(Pool))),
1065
+ thread_pool_create(Pool, 10, []).
1066
+
1067
+
1068
+ /*******************************
1069
+ * WAIT POLICIES *
1070
+ *******************************/
1071
+
1072
+ :- meta_predicate
1073
+ thread_repeat_wait(0).
1074
+
1075
+ %! thread_repeat_wait(:Goal) is multi.
1076
+ %
1077
+ % Acts as `repeat, thread_idle(Goal)`, choosing whether to use a
1078
+ % `long` or `short` idle time based on the average firing rate.
1079
+
1080
+ thread_repeat_wait(Goal) :-
1081
+ new_rate_mma(5, 1000, State),
1082
+ repeat,
1083
+ notrace,
1084
+ update_rate_mma(State, MMA),
1085
+ long(MMA, IsLong),
1086
+ ( IsLong == brief
1087
+ -> call(Goal)
1088
+ ; thread_idle(Goal, IsLong)
1089
+ ).
1090
+
1091
+ long(MMA, brief) :-
1092
+ MMA < 0.05,
1093
+ !.
1094
+ long(MMA, short) :-
1095
+ MMA < 1,
1096
+ !.
1097
+ long(_, long).
1098
+
1099
+ %! new_rate_mma(+N, +Resolution, -State) is det.
1100
+ %! update_rate_mma(!State, -MMA) is det.
1101
+ %
1102
+ % Implement _Modified Moving Average_ computing the average time
1103
+ % between requests as an exponential moving average with alpha=1/N.
1104
+ %
1105
+ % @arg Resolution is the time resolution in 1/Resolution seconds. All
1106
+ % storage is done in integers to avoid the need for stack freezing in
1107
+ % nb_setarg/3.
1108
+ %
1109
+ % @see https://en.wikipedia.org/wiki/Moving_average
1110
+
1111
+ new_rate_mma(N, Resolution, rstate(Base, 0, MaxI, Resolution, N, 0)) :-
1112
+ current_prolog_flag(max_tagged_integer, MaxI),
1113
+ get_time(Base).
1114
+
1115
+ update_rate_mma(State, MMAr) :-
1116
+ State = rstate(Base, Last, MaxI, Resolution, N, MMA0),
1117
+ get_time(Now),
1118
+ Stamp is round((Now-Base)*Resolution),
1119
+ ( Stamp > MaxI
1120
+ -> nb_setarg(1, State, Now),
1121
+ nb_setarg(2, State, 0)
1122
+ ; true
1123
+ ),
1124
+ Diff is Stamp-Last,
1125
+ nb_setarg(2, State, Stamp),
1126
+ MMA is round(((N-1)*MMA0+Diff)/N),
1127
+ nb_setarg(6, State, MMA),
1128
+ MMAr is MMA/float(Resolution).
1129
+
1130
+
1131
+ /*******************************
1132
+ * MESSAGES *
1133
+ *******************************/
1134
+
1135
+ :- multifile
1136
+ prolog:message/3.
1137
+
1138
+ prolog:message(httpd_started_server(Port, Options)) -->
1139
+ [ 'Started server at '-[] ],
1140
+ http_root(Port, Options).
1141
+ prolog:message(httpd_stopped_worker(Self, Status)) -->
1142
+ [ 'Stopped worker ~p: ~p'-[Self, Status] ].
1143
+ prolog:message(httpd_restarted_worker(Self)) -->
1144
+ [ 'Replaced aborted worker ~p'-[Self] ].
1145
+ prolog:message(httpd(created_pool(Pool))) -->
1146
+ [ 'Created thread-pool ~p of size 10'-[Pool], nl,
1147
+ 'Create this pool at startup-time or define the hook ', nl,
1148
+ 'http:create_pool/1 to avoid this message and create a ', nl,
1149
+ 'pool that fits the usage-profile.'
1150
+ ].
1151
+
1152
+ http_root(Address, Options) -->
1153
+ { landing_page(Address, URI, Options) },
1154
+ [ url(URI) ].
1155
+
1156
+ landing_page(Host:Port, URI, Options) :-
1157
+ !,
1158
+ must_be(atom, Host),
1159
+ must_be(integer, Port),
1160
+ http_server_property(Port, scheme(Scheme)),
1161
+ ( default_port(Scheme, Port)
1162
+ -> format(atom(Base), '~w://~w', [Scheme, Host])
1163
+ ; format(atom(Base), '~w://~w:~w', [Scheme, Host, Port])
1164
+ ),
1165
+ entry_page(Base, URI, Options).
1166
+ landing_page(unix_socket(Path), URI, _Options) :-
1167
+ !,
1168
+ format(string(URI), 'Unix domain socket "~w"', [Path]).
1169
+ landing_page(Port, URI, Options) :-
1170
+ landing_page(localhost:Port, URI, Options).
1171
+
1172
+ default_port(http, 80).
1173
+ default_port(https, 443).
1174
+
1175
+ entry_page(Base, URI, Options) :-
1176
+ option(entry_page(Entry), Options),
1177
+ !,
1178
+ uri_resolve(Entry, Base, URI).
1179
+ entry_page(Base, URI, _) :-
1180
+ http_absolute_location(root(.), Entry, []),
1181
+ uri_resolve(Entry, Base, URI).