-
Notifications
You must be signed in to change notification settings - Fork 7.8k
RFC - Added the apache_connection_stream() function for CGI WebSockets #14047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…cket Apache CGI doesn't support WebSocket Upgrade requests out-of-the-box. php://input uses apache brigade/buckets but these are not fired with websocket Input; moreover, the php://input stream is cached and not seekable. php://stdio is the php code buffer so it is not useful here either. This allow a direct connection to the client.
…cket for CGI WebSockets
What email address did you fill in for the last input box? I'm guessing you perhaps filled in your own email address? |
…hp-src into apache_connection_stream
When a connection is received you must hit enter in your server terminal to complete the connection. CLI server is single threaded, so only basic debugging can be done regarding websockets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't really comment on the technical aspect of this PR, but there are some non-technical issues I've spotted.
@@ -19,6 +19,10 @@ | |||
# Various temporary generated files | |||
*.tmp | |||
|
|||
# editor includes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the comment at the top of this file: IDE specific files should be in a local .gitignore.
@@ -215,23 +215,20 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa | |||
} | |||
|
|||
if (!strcasecmp(path, "input")) { | |||
php_stream_input_t *input; | |||
|
|||
php_stream_input_t *input; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -41,6 +41,7 @@ ZEND_FUNCTION(apache_lookup_uri); | |||
ZEND_FUNCTION(virtual); | |||
ZEND_FUNCTION(apache_request_headers); | |||
ZEND_FUNCTION(apache_response_headers); | |||
ZEND_FUNCTION(apache_connection_stream); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment on top of this file. This file is generated from the .stub.php file and should not be manually edited.
The accepted practice for WebSockets (WS) in Apache PHP is to use the
stream_context_create
is a PHP CLI process that Apache’smod_proxy
andmod_proxy_wstunnel
forward connections to. This requires that you bind to an open port and have access to install Apache modules. The IETF standardized the WebSocket protocol as RFC 6455 in 2011 to enable full duplex communication. The issue Apache2handler PHP currently has is its ability to capture persistent input connections in a php_stream to then be used with stream_select. PHP-defined IO streams are currently not able to handle the requests asphp://stdio
is the actual code buffer andphp://input
is tied to HTTPD'sap_get_brigade
function which acts as a wrapper to handle io filtering. Not only doesap_get_brigade
not capture WS input, but it also caches the data as Apache2handler expects it to be static. PHP’sstream_select
function also fails to cast this non-sealable stream (as expected). HTTPD can handle long upgrade connections, and according to the spec, the WS protocol is just an HTTP GET request with specific headers and io filters. This proposed addition includes a visual sample and example repository.Here is a link to the repository with the full code example for both PHP-CLI WebSockets and PHP-SAPI
apache_websocket_stream
. The boilerplate is consistent in all the examples on the internet except for"Content-Length: 0”
and"Content-Type: application/octet-stream”
headers, this causes apache to disable its output buffer and output filter (compression encoding) and allows our binary data to pass.The alternative to WebSockets is Long Polling, aka request interval polling. This is popular with CMS like WordPress due to its reliability, but is considered a poor option that only emulates real-time io with significant roundtrip overhead.
I believe this trade-off is made all too often by developers who:
sudo
access.mod_proxy
or other Apache configurations that have to happen for a proper CLI implementationThis method is designed to be a zero configuration open with no external Apache Modules or configurations. Using it over long term request reties will help save organizations electricity and allowing the features to be available out of the box should help shorten the learning curve for the community. If this proposal is well received then I believe the next logical step is to add the protocol framing layer in php-src too.