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.12k stars 1.01k forks source link

Middleware #141

Open joewalnes opened 9 years ago

joewalnes commented 9 years ago

I'd like to be able to add middleware handlers. These are roughly equivalent to Rack or WSGI Middleware, Java Filters, etc.

Apps can configure a stack of 0 to N handlers that get invoked on each request. The can do things like modify inbound/outbound content (headers, websocket messages, static/cgi pages, etc).

Use cases:

I haven't fleshed out details for exactly how this should work, but in the spirit of websocketd, it would be ideal if each of these middleware components was a user defined executable that could be written in any language. Some of them may be short lived (e.g. path rewriting), whereas others may live for the complete lifetime of the connection (e.g. message compress).

krzysztofantczak commented 9 years ago

+1 - it would allow to write middleware for really simple shell scripts which can be executed on each request - simple way to extend websocketd functionality with any kind of language, if script execution is based only on STDIN/OUT and exit code ;-)

novelistparty commented 7 years ago

several ideas on this:

websocketd --middlewaredir=handlers


Another way to add middleware tasks is to pass a list of programs to websocketd; it would call them exactly like a pipeline on the shell:

./service | ./logger | ./compression | ./format_converter | ./path_rewriter

would be plugged into websocketd with

websocketd ./service ./logger ./compression ./format_converter ./path_rewriter

There might be a way to pass that pipeline command directly to websocketd, but it would require some escaping/quoting/subshell-wrangling that makes bash a headache at times.

asergeyev commented 7 years ago

Yes, as you said pipelines are something that's already possible with current websocketd, something like

websocketd bash -c './script | ./script'

Similarly you can create bunch of scripts that implement calls using "middleware" and put it to series of files and use --dir for them. So really there is no feature if we stay in line protocol mode.

I think what Joe had in mind is more HTTP-ish handlers, which may be working before/after script is called and have access to context of the HTTP request...

Say it's CGI scripts, we may have "onConnect", "onDisconnect" scripts for now... Should there be others? Each script modifies context of the request. onConnect can set HTTP headers which passed to main script as CONNECT_HEADERNAME variables. There could be only one onConnect so if you need multiple you write wrapper execute scripts you need and figure what to return, it's not a websocketd problem to figure merge strategy.

onDisconnect gets executed with additional HTTP headers in request signifying all those variables (X_CONNECT_HEADER_NAME), used protocol, script command, exit code, reason for disconnect, bytes received/sent from client, and maybe others...

I can spec it more and even write it into code... Just need more support on "where it could be helpful"

I don't think we can have more handlers... IMO all compression of websocket exchange should be done in websocketd itself, I see large problems to keep chain of piped scripts together under websocketd management, IMO it's unnecessary when you can outsource it to bash running them in way you want. So middleware for changing messages and/or filtering input is down to user's responsibilities... Please find example where I might be wrong. I just feel it could be implemented in three stages...

onConnect additionally may have option to prohibit protocol upgrade by not returning 1xx / 2xx response... Not sure on that.

asergeyev commented 6 years ago

We need to form middleware API here....

What actual things websocket knows that it can share with middleware about webclient to script link that's worth sharing....

What actions we want to allow API to do to either end of those links?

Is there good inspiration middlewares in unix world that we know?

juan-morales commented 5 years ago

Would this break the UNIX philosophy of "Write programs that do one thing and do it well....." ... ?

maxwellb commented 5 years ago

Maybe follow what Git does for credential helpers. Define an interface that websocketd will send a program, and that program is expected to return certain responses. For example, you could define an "input" interface that would take the same CGI variables in the environment, some representation of the connection (toml perhaps) on stdin, and be expected to set error code and/or format its output in a certain way, which websocketd will then interpret. Same for output. Then you can pass on on the command line websocketd -input ./auth.sh -output ./cache-control.sh ./example