mod_perl
mod_perl
的主要作用在于将 Perl 的解释器嵌入到 Apache 中.
感觉比较重要的几个模块:
CGI
Apache::Registry
Apache::PerlRun
学习 CGI 脚本的编写只需要处理好两件事:
- how to accept data
- how to generate output
主要就是接收 header
内容, 做修改后将新的 header
发送给服务器软件处理.
一个最简单的 CGI 脚本:
1 |
|
一般在 Web Server 的配置目录下都有 mime.types
文件, 其包含 a list of MIME types.
注意: 根据 HTTP 协议要求, header 之后必须要有一个空行 (也就是这里为什么是 \n\n
), 其表明响应信息的开始.
在 Apache 中:
1 |
|
中的 username=Doug
被称为 QUERY_STRING
mod_cgi
运行在 mod_cgi
之下, GATEWAY_INTERFACE
环境变量的值为 CGI/1.1
, 而运行在 mod_perl
之下, 其值为 CGI-Perl/1.1
REMOTE_ADDR
显示服务器的 IP.
REQUEST_METHOD
显示访问的方式.
QUERY_STRING
显示请求的参数.
HTTP_USER_AGENT
显示访问者的 user agent.
注意 QUERY_STRING
的长度有限制, 在 Apache 中为 8KB. 更多的数据通过 POST 提交.
mod_perl
相对于 mod_cgi
的优势
mod_cgi
中运行 Perl 程序时, 每一次请求都会加载和结束一次 Perl 解析器 (都会重新 fork), 且所有变量都会重新声明和使用.
在使用 mod_perl
时, Perl 解析器在一个 child process 中只加载一次, 在这个 child process 处理完一个 Perl 脚本之后, 其不会 exit. 因此代码也只被载入和编译一次.
mod_perl
也包含 Apache core 的 API, 因此可以用 Perl 编写 Apache 的完整模块. 也可以完全用 Perl 配置 Apache.
在加载 mod_perl
之后, 可以用一些 mod_perl-specific
configuration directives 来配置, 其大多以 Perl
开头, 如:
1 |
|
等.
缺点为, 让 httpd
程序占用更多的内存.
.htaccess
文件
.htaccess
是 Hypertext Access 的缩写。是 Apache 的配置文件.
但其通常位于网站的根目录或特定目录中. 可以在不修改全局服务器配置文件而定制网站的行为.
但是如果在 httpd.conf
文件中编写了:
1 |
|
则 .htaccess
不会起作用, 除非某一个具体的目录设置 AllowOverride
为 None
以外的值.
也可以用 AccessFileName
让 Apache
寻找其他文件:
1 |
|
此时会找 .acl
而不是 .htaccess
对于 .ht*
文件, Apache 会设置让其不被 Web 访问, 而自定义时, 需要添加:
1 |
|
用 mod_perl
运行 CGI 脚本
主要用:
Apache::PerlRun
Apache::Registry
这两个模块.
注意两者的特点和区别:
Apache::Registry
, 只编译脚本一次, 所有全局变量值在多个 requsts 之间会保留.
Apache::PerlRun
, 每一个 requsts 都会编译脚本一次.
Apache::Registry
会检查脚本的 last-modification time, 如果文件被修改, 则重新编译.
Apache 会把一次 request 的处理分为多个 phases, 便于对某一个 phase 做 hook 处理.
用于处理特定 phase 的 subroutine 或 function 都被称为 handler
.
如处理 authentication 的 handler 有 mod_auth_dbi
, 处理内容的 handler 有 mod_cgi
mod_perl
和其他模块一样, 都是用 C 编写的. 但是其提供了用 Perl 编写 Apache 模块的 API.
对于如何切换 Apache::PerlRun
和 Apache::Registry
, 在 Apache 配置文件中添加如:
1 |
|
一个简单的 mod_perl
Content Handler
如, 编写一个 ModPerl::Rules1
的模块:
1 |
|
将其放在 @INC
的路径中.
另一个 ModPerl::Rules2
模块:
1 |
|
在 /etc/httpd/conf/httpd.conf
文件中添加:
1 |
|
然后就能直接访问到 CGI 脚本.
从这里可以得到几点:
PerlHandler
, 指定将 requsts 传送给哪一个 Perl 模块处理, 其会自动调用相应模块中的handler
函数PerlSendHeader On
, 让 Apache 在请求处理过程中自动发送适当的 HTTP 头部,例如 Content-Type 和 Content-Length
多种 mod_perl
安装
先获取 Apache 和 mod_perl
的源代码:
1 |
|
注意这里的版本. 且这里用的是 mod_perl2
解压之后, 主要依靠 perl Makefile.PL
进行配置.
perl Makefile.PL 的选项
具体还是看书吧.
启用 callbacks hooks
可选的有:
注意除了 PerlHandler
, PerlChildInitHandler
, PerlChildExitHandler
, PerlConnectionApi
, PerlServerApi
这些是默认可用的, 其余需要在 perl Makefile.PL
时添加参数来配置.
开启所有 callback hooks, 添加:
1 |
|
或者:
1 |
|
启用标准的 API 特性
有:
PERL_FILE_API=1
PERL_TABLE_API=1
PERL_LOG_API=1
PERL_URI_API=1
PERL_UTIL_API=1
PERL_CONNECTION_API=1
PERL_SERVER_API=1
都是启用 Perl 模块的使用, 如 Apache::File
.
这些选项都是默认关闭的, 可以用 EVERYTHING=1
或者 DYNAMIC=1
全部启用.
启用额外的特性
- 用
<Perl>
section 在httpd.conf
文件中用 Perl 语言直接配置 Apache
1 |
|
- SSI 技术支持
1 |
|
- 启用
Apache::ModuleConfig
, 和Apache::CmdParms
1 |
|
- stacked handlers
1 |
|
- method handlers
1 |
|
复用配置参数
将配置选项写入 makepl_args.mod_perl
(还有其他形式) 文件中, Makefile.PL
会自动读取.
Apache 和 mod_perl
配置
Apache 配置
若不想 .htaccess
默认起作用, 可以在 httpd.conf
文件中加入:
1 |
|
此时若还想 .htaccess
文件起作用, 需要在特定目录的配置中加入 AllowOverride
除 None
以外的值.
为了防止外部访问, 一般需要加上:
1 |
|
更改端口
1 |
|
修改子进程的用户和组
1 |
|
<Directory>
, <Location>
, 和 <Files>
Sections
<Directory>
一般 <Directory>
作用于目录. 用绝对路径, 相对于 server 的根目录:
1 |
|
<Files>
<Files filename>...</Files>
可以写在 server 和 virtual host 的配置中, 以及 .htaccess
文件.
<Files>
作用于一个或多个文件.
<Files>
section 可以嵌套在 <Directory>
中, 但不能嵌套在 <Location>
中.
可以通过 ~
启用扩展正则:
1 |
|
嵌套的示例如:
1 |
|
这里 PerlHandler
之后的 +
表明让 mod_perl
加载 Apache::Compress
模块.
<Location>
<Location URI>...</Location>
可以写在 server 和 virtual host 的配置文件中.
<Location>
作用于 URI. 相对路径, 相对于设置的一些根目录:
1 |
|
作用于不存在于文件系统的路径如:
1 |
|
处理顺序
<Directory>
和.htaccess
<DirectoryMatch>
和<Directory ~ >
<Files>
和<FilesMatch>
<Location>
和<LocationMatch>
<Directory>
先处理短路径, 后处理长路径, 如先 /
, 后 /home/www
.
mod_perl
配置
最好是把 mod_perl
的配置放在 Apache 配置文件的最后.
或者是外部引用, 如:
1 |
|
mod_perl
引入了几个新的 directives:
<Perl>
PerlModule
PerlRequire
<Perl>
其允许在 Apache 配置文件中嵌入 Perl 代码. 如:
1 |
|
PerlModule
等价于 Perl 中的 use
.
同样用于加载 Perl 模块:
1 |
|
可以一次加载多个.
PerlRequire
等价于 Perl 中的 require
.
用于加载一个 Perl 模块或脚本, 如:
1 |
|
注意这里的 startup.pl
的最后一行写成 1;
Alias 配置
Web 中大多访问的路径都不是物理存在的, 而是通过映射到物理路径上.
在 Apache 中可以用 ScriptAlias
和 Alias
进行映射, 如:
1 |
|
这里将 /foo
的请求映射到 /home/httpd/foo
目录. 如一个请求为 http://www.example.com/foo/test.pl
, 则会被处理为 /http://www.example.com/home/httpd/foo/test.pl
ScriptAlias
不仅会进行映射操作, 还会运行匹配的文件:
1 |
|
其相当于:
1 |
|
由于 SetHandler
调用 mod_cgi
模块, 因此若想使用 mod_perl
, 最好还是用 Alias
, 如:
1 |
|
<Location /perl>
Sections
如:
1 |
|
Perl*Handlers
Apache 的 request loop 有 11 个 phases:
- Post-read-request
- URI translation
- header parsing
- access control
- authentication
- authorization
- MIME type checking
- fixup
- response
- logging
- cleanup
mod_perl
为每一个 phases 提供有 Handler:
- PerlPostReadRequestHandler
- PerlInitHandler
- PerlTransHandler
- PerlHeaderParseHandler
- PerlAccessHandler
- PerlAuthenHandler
- PerlAuthzHandler
- PerlTypeHandler
- PerlFixupHandler
- PerlHandler
- PerlLogHandler
- PerlCleanupHandler
mod_perl
还提供了一些额外的 Handler:
- PerlChildInitHandler
- PerlChildExitHandler
- PerlRestartHandler
- PerlDispatchHandler
默认情况下, 大部分的 Handler 是 disable 的, 需要在编译 mod_perl
时启用.
The handler()
subroutine
handler()
会在接收到 requests 时自动调用, 在一个 module 中定义了 handler()
后, 可以通过:
1 |
|
来使用, 但其不会预加载 Apache::Foo
.
handler()
函数接收两个参数:$r
和 $args
。其中,$r
是一个 Apache::RequestRec
对象,代表当前的请求对象,它包含了与请求相关的信息, 例如请求的 URI, 请求的头部信息等. $args
则是一个字符串, 包含了请求的查询参数.
若想预加载, 可以:
1 |
|
或者在 startup.pl
中加入:
1 |
|
或者写为:
1 |
|
其相当于:
1 |
|
的 alias.
若想使用 handler()
以外的名称如 my_handler()
, 可以写为:
1 |
|
查看当前运行的 handler:
1 |
|