Sula:用 Scryer Prolog 编写的 Gemini 协议服务器

Hacker News Top 工具

摘要

Sula 是一个用 Scryer Prolog 编写的 Gemini 协议服务器,具有通过 rustls 实现的 TLS、内容协商和优雅关闭功能,但需要修补过的 Scryer Prolog 构建版本。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/08/05 19:56

# Sula 来源:https://sagredo.dev/projects/sula/ > `/'su\.la/` 取自西班牙语中“胶囊”的后缀,Cápsula。 sula 徽标 Git(https://git.sagredo.dev/?p=sula.git;a=summary) 一个用 Scryer Prolog(https://www.scryer.pl/)编写的 Gemini(https://geminiprotocol.net/)协议服务器。 ## 要求 sula 依赖于打了补丁的 Scryer Prolog,可在 此处(https://git.sagredo.dev/scryer-prolog)找到(分支 `js/fixes`)。所需的补丁包括: - 原生 `'$copy_stream'/2` 内置谓词,用于将二进制文件体流式传输给 TLS 客户端,而无需将内容物化到 Prolog 堆上。 - 对 `library(pio)` 的 `buffer_prepare_for_n/5` 的修复,使得从进程管道(以及其他 `at_end_of_stream/1` 永远不会报告 true 的流)惰性读取时,在 EOF 处终止而不是空转。 - 在 `socket_server_accept/4` 中加入非阻塞轮询循环,检查 Scryer 的 `INTERRUPT` 标志,以便 `SIGINT` 变成可捕获的 `'$interrupt_thrown'` 异常,而不是被阻塞的系统调用卡住。 - 移植到 `rustls`。 - 修改 `tls_server_negotiate` 以包含可选的客户端证书。 构建并安装打过补丁的 Scryer: `` git clone https://git.sagredo.dev/scryer-prolog -b js/fixes cd scryer-prolog cargo install --path . `` `openssl(1)` 也必须位于 `PATH` 中——它在启动时被调用,从配置的身份证书中读取 `CN`,并验证它与配置的主机名匹配。 ## 运行 `` ./sula.pl --addr HOST:PORT --hostname NAME --content DIR --certs DIR `` `sula.pl` 是一个多语言脚本:bash 检测到 `PATH` 上的 `scryer-prolog`,并以 `sula:run, halt` 作为入口目标执行它。 示例: `` ./sula.pl \ --addr 127.0.0.1:1965 \ --hostname gmi.example.dev \ --content ./site \ --certs . `` ### 命令行选项 所有选项接受任意顺序。任何未识别的选项都会被静默丢弃。 选项含义默认值`--addr HOST:PORT`监听 socket 的绑定地址和端口`127.0.0.1:1965``--hostname NAME`证书的预期 `CN`。不匹配时启动中止`localhost``--content DIR`服务文件的根目录`./site``--certs DIR`包含 `cert.pem` 和 `key.pem` 的目录`.`### 停止服务器 `Ctrl+C` 触发干净关闭:监听 socket 被关闭,顶层 catch 记录 `Shutting down`,进程以 0 退出。 ## 特性 - TLS 通过 `rustls`,PKCS#12 身份文件。 - 主机名验证:启动时,`cert_is_for_hostname/2` 调用 `openssl x509`,并断言证书的 `CN` 与 `--hostname` 匹配。 - 通过 `mime/2` 按扩展名进行内容协商,内容在启动时从 `/etc/mime.types`(由 `mime.pl` 中的 DCG 解析)填充。为 `.gmi` 添加了 `text/gemini`。 - 文本响应通过 `format/3` 发送;二进制响应在原生代码中通过 `copy_stream/2`(文件 → TLS socket,不经过 Prolog 堆)流式传输。 - 每连接错误处理:TLS 握手失败和流中间客户端断开连接会被记录,循环继续。其他错误会重新抛出并显示在顶层。 - 通过打补丁的 Scryer `socket_server_accept/4` 在 `SIGINT` 时优雅关闭。 ## 布局 `` sula.pl 多语言启动器 + 主 sula 模块(run/0,请求循环)。 config.pl CLI 解析(DCG)和配置访问器(cert/1,addr/1,…)。 cert.pl 证书加载 + 主机名对 CN 检查。 mime.pl /etc/mime.types 解析器(DCG)和 mime/2 事实。 request.pl 请求行读取器。 gemini_uri.pl Gemini URI DCG(gemini://host[:port]/path[?query])。 ip.pl IP 地址识别(作为 Gemini 主机被拒绝)。 response.pl 响应状态码 DCG。 log.pl 带标签的 log_msg/3。 banner.pl 读取 banner.txt 并通过 display_banner/1 逐行输出。 `` ## 计划中的功能 - 使用密钥和证书而不是 identity.p12 - 客户端证书 - 从配置文件加载配置 - 保存和加载用户 - 运行 CGI 脚本 - 所有状态码 - 速率限制 - 虚拟主机 - 文件日志 - 多线程或类似? - 热重载?

相似文章

yserver: 一个用Rust从头编写的现代X11服务器

Lobsters Hottest

yserver是一个用Rust从头编写的现代X11服务器,能够运行MATE、XFCE和Cinnamon等完整的桌面环境,同时去掉了遗留的负担。它支持多种X扩展,并已在多种硬件上测试过。

alireza0/s-ui

GitHub Trending (daily)

S-UI 是一个基于 SagerNet/Sing-Box 构建的高级 Web 面板,用于管理多协议代理配置,具备流量路由、订阅链接和多语言支持等功能。