Skip to content

Add --passstderr flag to forward STDERR through WebSocket#459

Open
Formatted wants to merge 1 commit into
joewalnes:masterfrom
Formatted:passstderr-feature
Open

Add --passstderr flag to forward STDERR through WebSocket#459
Formatted wants to merge 1 commit into
joewalnes:masterfrom
Formatted:passstderr-feature

Conversation

@Formatted
Copy link
Copy Markdown

Summary

Adds a --passstderr CLI flag that forwards STDERR output from the wrapped process to WebSocket clients as tagged JSON messages.

Addresses: #403 (Feature Request: STDERR redirected through websockets, open since 2021)

Problem

Currently, STDERR output from subprocesses is silently swallowed — it's only logged on the server side and never reaches the WebSocket client. This makes debugging scripts nearly impossible, as warn/die in Perl, Python tracebacks, and other error output is invisible to clients.

Solution

When --passstderr is enabled:

  • STDERR lines are forwarded as JSON: {"stream":"stderr","data":"error message"}
  • STDOUT lines are also tagged for consistency: {"stream":"stdout","data":"output line"}
  • The output channel closes only after both STDOUT and STDERR complete, ensuring no messages are lost

When --passstderr is not set (default), behavior is unchanged — STDERR is only logged server-side.

Example

websocketd --port=8080 --passstderr ./myscript.sh

Client receives:

{"stream":"stdout","data":"normal output"}
{"stream":"stderr","data":"warning: something went wrong"}

Client-side usage

ws.onmessage = function(event) {
  var msg = JSON.parse(event.data);
  if (msg.stream === 'stderr') {
    console.error(msg.data);
  } else {
    console.log(msg.data);
  }
};

Changes

  • libwebsocketd/config.go — Added PassStderr field to Config
  • libwebsocketd/process_endpoint.go — Added passStderr parameter to NewProcessEndpoint, new readStdoutTagged/readStderrTagged methods with sync.WaitGroup, and tagMessage helper with proper JSON escaping
  • libwebsocketd/handler.go — Wire PassStderr config through to NewProcessEndpoint
  • config.go — Added --passstderr CLI flag
  • help.go — Updated help text
  • README.md — Mentioned new flag in features list
  • CHANGES — Added changelog entry
  • libwebsocketd/process_endpoint_stderr_test.go — 3 unit tests covering the feature

Testing

  • All 217 existing tests pass
  • 3 new tests added:
    1. STDERR forwarded as JSON when passStderr enabled
    2. STDERR not forwarded when passStderr disabled
    3. Output channel closes after both STDOUT and STDERR complete
  • Built and vetted on Go 1.21

…alnes#403)

When --passstderr is enabled, STDERR output from the wrapped process
is forwarded to WebSocket clients as tagged JSON messages:
  {"stream":"stderr","data":"error message"}

STDOUT messages are also tagged for consistency:
  {"stream":"stdout","data":"output line"}

This addresses the long-standing issue (joewalnes#403) where STDERR was
silently swallowed, making it impossible for clients to see error
output from their scripts (e.g., Perl warn, Python tracebacks).

The output channel now closes only after both STDOUT and STDERR
goroutines complete, ensuring no messages are lost.

- Added PassStderr field to libwebsocketd.Config
- Added passStderr parameter to NewProcessEndpoint
- Added readStdoutTagged/readStderrTagged methods with sync.WaitGroup
- Added tagMessage helper with proper JSON string escaping
- Added 3 unit tests covering the new behavior
- Updated --help text and README
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant