joewalnes / websocketd

Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.
http://websocketd.com/
BSD 2-Clause "Simplified" License
17.16k stars 1.01k forks source link

how to get a response like 'Clean: true, ..' after script executed #440

Open standzhou2 opened 1 year ago

standzhou2 commented 1 year ago

greeter.py

#!/usr/bin/env python
# encoding: utf-8
from sys import stdin, stdout

# For each line FOO received on STDIN, respond with "Hello FOO!".
while True:
  line = stdin.readline().strip()
  if line == 'bye':
     print('bye')
     stdout.flush()
     break
  print('Hello %s!' % line)
  stdout.flush() # Remember to flush

start command ./websocketd -port 8889 --loglevel debug --ssl --sslcert=cert/server.crt --sslkey=cert/server.key --dir=script --devconsole

in this case , browser side got a response like 'Clean: false..' i want to get a response with 'Clean: true,.., what's wrong with my script above, help pls

image

matvore commented 1 year ago

According to reference [0], closing cleanly requires that one end send the bytes 0xff, 0x00

In python3, I guess that means: sys.stdout.buffer.write(bytes([0xff, 0x00]))

I'm not sure off the top of my head if websocketd handles this as expected, as it does split frames on \n bytes, so it doesn't exactly treat the subproc's outgoing bytes as raw bytes.

[0] https://stackoverflow.com/questions/4812686/closing-websocket-correctly-html5-javascript#:~:text=To%20close%20the%20connection%20cleanly%2C%20a%20frame%20consisting%20of%20just%20a%200xFF%20byte%20followed%20by%20a%200x00

On Wed, Apr 19, 2023 at 10:52 AM standzhou2 @.***> wrote:

greeter.py

!/usr/bin/env python

encoding: utf-8

from sys import stdin, stdout

For each line FOO received on STDIN, respond with "Hello FOO!".

while True: line = stdin.readline().strip() if line == 'bye': print('bye') stdout.flush() break print('Hello %s!' % line) stdout.flush() # Remember to flush

start command ./websocketd -port 8889 --loglevel debug --ssl --sslcert=cert/server.crt --sslkey=cert/server.key --dir=script --devconsole

i want to get response like 'Clean: true..', but i got 'Clean: false', what should i do to get response like 'Clean: true...h'

[image: image] https://user-images.githubusercontent.com/119867339/233130640-4645150b-0fb9-4903-8c60-c632decab9be.png

— Reply to this email directly, view it on GitHub https://github.com/joewalnes/websocketd/issues/440, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHHDTKWSUVNPTA2J6QGGBTXCAC2TANCNFSM6AAAAAAXEIXV5U . You are receiving this because you are subscribed to this thread.Message ID: @.***>

standzhou2 commented 1 year ago

thank you so much i just have a try, it seems not work.

image

image

matvore commented 1 year ago

I looked a little more closely.

The gorilla/websocket library that websocketd uses allows sending a CloseMessage and other control messages, but websocketd doesn't expose an API to use that.

If you attempt to write 0xff, 0x00 or other control codes in the websocket script, websocketd ends up treating that as plain data, and wrapping that in a data packet when sending to the client. This includes the case of passing --binary to websocketd.

Maybe you can use some app-specific indicator, a normal data packet, for the server to communicate clean closure?

ctn-malone commented 1 year ago

If you're under linux, you can try to use https://github.com/ctn-malone/websocketd-controller which can be used as a wrapper around your script and will forward stdout, stderr & exit event (which contain the exit code of the wrapped script)

asergeyev commented 1 year ago

What is difference that clean:true would make?

ctn-malone commented 1 year ago

It’s just an easy way to get json events everytime something is outputted to stdout, stderr or if the program exits. I like the standard way of communicating it provides but I might be a bit biased 😅

Edit: on second thought, I probably misread @asergeyev question (I thought you asked what benefit would be provided by the wrapper)