是否可以用 PHP 编写 Apache 协议处理程序?
我想知道是否以及如何可以在 PHP 中为 Apache 2 编写自定义“协议处理程序”(在自定义端口监听)?
在 C 和 mod_perl 中,您可以编写所谓的“协议处理程序”,它拦截早期的 Apache 阶段(在客户端套接字连接被接受()之后,但在写入任何内容之前)并且可以例如处理 < a href="http://httpd.apache.org/mod_ftp/" rel="nofollow">FTP 或 SMTP 协议。 PHP 中也可以吗?
例如,我有以下简单的 mod_perl 处理程序,我想将其移植到 PHP(以比较内存使用情况 - 因为我的 mod_perl 处理程序每个子进程需要 20m)。我的处理程序侦听端口 843 并将字符串 POLICY 写入客户端套接字:
package SocketPolicy;
# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
# <VirtualHost _default_:843>
# PerlModule SocketPolicy
# PerlProcessConnectionHandler SocketPolicy
# </VirtualHost>
use strict;
use warnings FATAL => 'all';
use APR::Const(-compile => 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile => qw(OK DECLINED));
use constant POLICY =>
qq{<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="8080"/>
</cross-domain-policy>
\0};
sub handler {
my $conn = shift;
my $socket = $conn->client_socket();
my $offset = 0;
# set the socket to the blocking mode
$socket->opt_set(APR::Const::SO_NONBLOCK => 0);
do {
my $nbytes = $socket->send(substr(POLICY, $offset),
length(POLICY) - $offset);
# client connection closed or interrupted
return Apache2::Const::DECLINED unless $nbytes;
$offset += $nbytes;
} while ($offset < length(POLICY));
my $slog = $conn->base_server()->log();
$slog->warn('served socket policy to: ', $conn->remote_ip());
return Apache2::Const::OK;
}
1;
谢谢, 亚历克斯
I wonder if and how it is possible to write a custom "protocol handler" (listening at a custom port) for Apache 2 in PHP?
In C and mod_perl you can write so-called "protocol handlers", which intercept the early Apache stage (after a client socket connection has been accept()ed, but before any content has been written to it) and can for example handle FTP or SMTP protocols. Is it possible in PHP as well?
For example, I have the following simple mod_perl handler, which I'd like to port to PHP (to compare the memory usage - since my mod_perl-handler needs 20m per child). My handler listens at the port 843 and writes the string POLICY to the client socket:
package SocketPolicy;
# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
# <VirtualHost _default_:843>
# PerlModule SocketPolicy
# PerlProcessConnectionHandler SocketPolicy
# </VirtualHost>
use strict;
use warnings FATAL => 'all';
use APR::Const(-compile => 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile => qw(OK DECLINED));
use constant POLICY =>
qq{<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="8080"/>
</cross-domain-policy>
\0};
sub handler {
my $conn = shift;
my $socket = $conn->client_socket();
my $offset = 0;
# set the socket to the blocking mode
$socket->opt_set(APR::Const::SO_NONBLOCK => 0);
do {
my $nbytes = $socket->send(substr(POLICY, $offset),
length(POLICY) - $offset);
# client connection closed or interrupted
return Apache2::Const::DECLINED unless $nbytes;
$offset += $nbytes;
} while ($offset < length(POLICY));
my $slog = $conn->base_server()->log();
$slog->warn('served socket policy to: ', $conn->remote_ip());
return Apache2::Const::OK;
}
1;
Thanks,
Alex
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,mod_php 不实现 mod_perl 所实现的 Apache 处理程序阶段。
请参阅 http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/sapi/apache2handler/php_functions.c?revision=296107&view=markup#l516
No, mod_php doesn't implement the Apache handler phases that mod_perl does.
See http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/sapi/apache2handler/php_functions.c?revision=296107&view=markup#l516
从技术上讲,是的,您可以使用套接字扩展,因为您还允许脚本运行足够长了。默认情况下,PHP 脚本将在 60 秒左右后终止。
所以主要问题是让 PHP 脚本像守护进程一样运行。
Technically yes you can with the socket extension given that you also allow you script to run long enough. By default a PHP script will be terminated after 60 sec or so.
So the main issue is to keep your PHP script running like a daemon.
这是完全有可能的......甚至还有一个用 PHP 编写的 完整的 Web 服务器
It's perfectly possible.... there's even a full web server written in PHP
是和否...PHP 有一个 Apache 接口,它使用 Apache 处理程序 API,以及其他接口,例如 CLI、CGI 等。PHP Apache API 集成选择不公开较低级别的处理细节,如 mod_perl 那样,因此如果您需要访问这些回调,您必须编写自己的 PHP Apache 处理程序 API 实现。
Yes and no.... PHP has an Apache interface which uses the Apache handler API, as well as other interfaces, such as CLI, CGI etc. The PHP Apache API integration chooses not to expose the lower-level handling details like mod_perl does, so if you need access to these callbacks you'll have to write your own PHP Apache handler API implementation.