Summary
envd's server-streaming RPCs (Process.Start, Process.Connect,
Filesystem.WatchDir) don't advertise to reverse proxies that their
responses are streaming. Behind a stock nginx (default
proxy_buffering on), chunks are held until the proxy buffer fills,
which makes interactive PTYs appear to accept input but produce no
output until something forces a flush.
The usual workaround — globally disabling proxy_buffering — also
gives up caching and weakens proxy_next_upstream retries for unary
RPCs that don't need streaming. Letting envd signal intent per
response is more surgical.
Affected handlers
process.Process/Start (process/start.go)
process.Process/Connect (process/connect.go)
filesystem.Filesystem/WatchDir (filesystem/watch.go)
Proposed fix
A small connect-go interceptor that sets X-Accel-Buffering: no on
server-streaming responses, wired into the existing
connect.WithInterceptors(...) chain. Unary and client-streaming RPCs
pass through unchanged.
X-Accel-Buffering is read by nginx (and other proxies that follow the
convention) on a per-response basis:
I have a patch ready (~60 LoC in a new internal/services/streaming
package + 2-line wiring per service + unit tests). Happy to open a PR
if the direction is right.
Summary
envd's server-streaming RPCs (
Process.Start,Process.Connect,Filesystem.WatchDir) don't advertise to reverse proxies that theirresponses are streaming. Behind a stock nginx (default
proxy_buffering on), chunks are held until the proxy buffer fills,which makes interactive PTYs appear to accept input but produce no
output until something forces a flush.
The usual workaround — globally disabling
proxy_buffering— alsogives up caching and weakens
proxy_next_upstreamretries for unaryRPCs that don't need streaming. Letting envd signal intent per
response is more surgical.
Affected handlers
process.Process/Start(process/start.go)process.Process/Connect(process/connect.go)filesystem.Filesystem/WatchDir(filesystem/watch.go)Proposed fix
A small connect-go interceptor that sets
X-Accel-Buffering: noonserver-streaming responses, wired into the existing
connect.WithInterceptors(...)chain. Unary and client-streaming RPCspass through unchanged.
X-Accel-Bufferingis read by nginx (and other proxies that follow theconvention) on a per-response basis:
I have a patch ready (~60 LoC in a new
internal/services/streamingpackage + 2-line wiring per service + unit tests). Happy to open a PR
if the direction is right.