Liking cljdoc? Tell your friends :D

im.ttalk.agent.server.adapter.http-kit

http-kit 的垫片:让它也能发 Ring SPEC 的流式正文(ring.core.protocols/StreamableResponseBody)。

http-kit 2.8 的 adapter 不认识 SPEC 的流式正文(直接 500「not understandable」),惰性 seq / 管道 InputStream 正文 它也是攒满了才发(designs/server-module.md §1 的实测)。本中间件把这样的响应改走 http-kit 自己的 as-channel: 先发状态码与头,再在一条虚拟线程上 write-body-to-stream 到一个转发给 send! 的 OutputStream,每次 write 即推送。

(require '[org.httpkit.server :as hk]
         '[im.ttalk.agent.server.adapter.http-kit :as hk-shim])
(hk/run-server (hk-shim/wrap-streaming handler) {:port 3000})
  • 只改直接实现 StreamableResponseBody 接口的正文(reify / deftype,如 im.ttalk.agent.server.sse 的 SSE 正文); String、byte[]、File、InputStream、seq 这些 Ring 经 extend 支持的照旧交给 http-kit。不是 http-kit 发来的请求 (没有 :async-channel)原样放过。
  • 对端断开(http-kit 的 :on-close)⇒ 之后的写抛 IOException ⇒ SSE 流记 gone?、producer 据此收尾。 ⚠️ 已知局限(http-kit 2.8 实测,2026-11-10):客户端断开后 http-kit 的 send! 仍回 true、open? 仍为 true、 :on-close 不触发(关套接字后连写 40 次、每次 8 KB 都「成功」)。所以在 http-kit 上 SSE 发现不了断连:流一直写到 producer 自己结束——AG-UI 的 run 照常跑完、/stop 照常可用,但 :orphan-cancel-ms(最后一个订阅者走了就按停)不会生效。 要断连检测请用 Jetty(缺省)或 Undertow。
  • 不引 http-kit 的硬依赖:requiring-resolve 取 org.httpkit.server,用 http-kit 的人自己的 classpath 上有它。
http-kit 的垫片:让它也能发 **Ring SPEC 的流式正文**(`ring.core.protocols/StreamableResponseBody`)。

http-kit 2.8 的 adapter 不认识 SPEC 的流式正文(直接 500「not understandable」),惰性 seq / 管道 InputStream 正文
它也是攒满了才发(designs/server-module.md §1 的实测)。本中间件把这样的响应改走 http-kit 自己的 `as-channel`:
先发状态码与头,再在一条虚拟线程上 `write-body-to-stream` 到一个转发给 `send!` 的 OutputStream,每次 write 即推送。

```clojure
(require '[org.httpkit.server :as hk]
         '[im.ttalk.agent.server.adapter.http-kit :as hk-shim])
(hk/run-server (hk-shim/wrap-streaming handler) {:port 3000})
```

- 只改**直接实现** `StreamableResponseBody` 接口的正文(reify / deftype,如 `im.ttalk.agent.server.sse` 的 SSE 正文);
  String、byte[]、File、InputStream、seq 这些 Ring 经 `extend` 支持的照旧交给 http-kit。不是 http-kit 发来的请求
  (没有 `:async-channel`)原样放过。
- 对端断开(http-kit 的 `:on-close`)⇒ 之后的写抛 IOException ⇒ SSE 流记 `gone?`、producer 据此收尾。
  ⚠️ **已知局限**(http-kit 2.8 实测,2026-11-10):客户端断开后 http-kit 的 `send!` 仍回 true、`open?` 仍为 true、
  `:on-close` 不触发(关套接字后连写 40 次、每次 8 KB 都「成功」)。所以在 http-kit 上 **SSE 发现不了断连**:流一直写到
  producer 自己结束——AG-UI 的 run 照常跑完、`/stop` 照常可用,但 `:orphan-cancel-ms`(最后一个订阅者走了就按停)不会生效。
  要断连检测请用 Jetty(缺省)或 Undertow。
- 不引 http-kit 的硬依赖:`requiring-resolve` 取 `org.httpkit.server`,用 http-kit 的人自己的 classpath 上有它。
raw docstring

im.ttalk.agent.server.adapter.undertow

Undertow(luminus/ring-undertow-adapter)的垫片:让它也能发 Ring SPEC 的流式正文 (ring.core.protocols/StreamableResponseBody)。

luminus 的 adapter 不认识 SPEC 的流式正文(直接 500「Body class not supported」),InputStream / seq 正文又是 攒满了才发(designs/server-module.md §1 的实测)。它的正文分派是一个开放协议 ring.adapter.undertow.response/RespondBody——install! 给它补上 StreamableResponseBody 接口的实现: 离开 IO 线程、startBlocking、把 exchange 的 OutputStream 交给 write-body-to-stream(每次 flush 即推送)、收尾。

(require '[ring.adapter.undertow :refer [run-undertow]]
         '[im.ttalk.agent.server.adapter.undertow :as ut-shim])
(ut-shim/install!)                       ;; 进程里调一次(幂等)
(run-undertow handler {:port 3000})

只影响直接实现该接口的正文(reify / deftype);String、InputStream 等照旧走 adapter 自己的实现。 不引 Undertow 的硬依赖:requiring-resolve 取协议,用 Undertow 的人自己的 classpath 上有它。

Undertow(`luminus/ring-undertow-adapter`)的垫片:让它也能发 **Ring SPEC 的流式正文**
(`ring.core.protocols/StreamableResponseBody`)。

luminus 的 adapter 不认识 SPEC 的流式正文(直接 500「Body class not supported」),InputStream / seq 正文又是
攒满了才发(designs/server-module.md §1 的实测)。它的正文分派是一个**开放协议**
`ring.adapter.undertow.response/RespondBody`——`install!` 给它补上 `StreamableResponseBody` 接口的实现:
离开 IO 线程、`startBlocking`、把 exchange 的 OutputStream 交给 `write-body-to-stream`(每次 flush 即推送)、收尾。

```clojure
(require '[ring.adapter.undertow :refer [run-undertow]]
         '[im.ttalk.agent.server.adapter.undertow :as ut-shim])
(ut-shim/install!)                       ;; 进程里调一次(幂等)
(run-undertow handler {:port 3000})
```

只影响**直接实现**该接口的正文(reify / deftype);String、InputStream 等照旧走 adapter 自己的实现。
不引 Undertow 的硬依赖:`requiring-resolve` 取协议,用 Undertow 的人自己的 classpath 上有它。
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close