缘由
今天看了 深入理解Nginx 第6章,看懂了书之后,利用了书上的代码自己测试了一下。测试的过程居然有点艰难,虽然最后还是完成了功能。但是还是暴露出两点:- 自己的基础知识不扎实
- 书中有些部分不严谨
所以这篇博客主要是我在阅读完成第六章之后,做实验过程中遇到的问题,而不是将http过滤模块讲清楚。
实验过程
从书的作者的blog下载第六章实例代码,- http://taohui.org.cn/ 的右边侧栏
然后解压
为了将charpter6目录里面的代码融入nginx,需要重新编译,我的编译。命令:
./configure --add-module=/home/asd/Downloads/chapter6 --without-http_rewrite_module --without-http_gzip_module --with-cc-opt='-g -O0' --with-debug
其中
- --add-module=/home/asd/Downloads/chapter6 这句是关键,这句就是将这个http模块(过滤模块也属于http模块)
- --without-http_rewrite_module: 不安装http rewrite module,我没有安装 PCRE库
- --without-http_gzip_module:不安装http gzip module
- --with-cc-opt='-g -O0':为了调试而加,-O0表示不优化
- --with-debug 需要打印debug调试级别的日志进nginx。
然后可以直接make和make install。
然后就是运行nginx,默认是运行这个份配置文件:/usr/local/nginx/conf/nginx.conf
但是为了运行这个例子作者给了我们一份config,所以请看我们就是用了作者的配置文件。
- 使用方式可以指定配置文件的位置,
- 也可以选择把默认的配置文件的位置给覆盖掉。
之后就困然了我1个多小时。
书中不严谨之处
我认为是在配置文件nginx.conf中:#user nobody;
worker_processes 1;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
keepalive_timeout 65;
server {
listen 8080;
location / {
root /;
add_prefix on;
}
}
}
请注意其中的location,根据root的作用,他直接指向了我们操作系统的目录,但是我在浏览器端输入的时候,就会得到403。
我觉得作者怎么做也太让我这样的初学者困惑了,当然我现在来看,就必须一个浏览器端输入一个能够访问的路径,而我们一般在使用浏览器的时候都以为直接会跳转到默认的首页,而且这个默认的首页应该是浏览器端能够访问的。作者要么在此处做个说明,要么就帮我们一个能够访问的路径嘛。
解决方案:
- 将 root /;
- 改为 root html;
text/plain和text/html
那么按照上面的改法改好了之后,可以访问到/usr/local/nginx/html/index.html,但是只有首页内容,没有我们添加的http过滤模块完成的功能:添加了字段[my filter prefix]。然后我就想了很久,这是因为源代码文件ngx_http_myfilter_module.c中有这么一段://myfilter过滤模块只处理Content-Type是"text/plain"类型的http响应
if (r->headers_out.content_type.len >= sizeof("text/plain") - 1
&& ngx_strncasecmp(r->headers_out.content_type.data, (u_char *) "text/plain", sizeof("text/plain") - 1) == 0)
{
//1表示需要在http包体前加入前缀
ctx->add_prefix = 1;
//如果处理模块已经在Content-Length写入了http包体的长度,由于
//我们加入了前缀字符串,所以需要把这个字符串的长度也加入到
//Content-Length中
if (r->headers_out.content_length_n > 0)
r->headers_out.content_length_n += filter_prefix.len;
}
注意必须要是text/plain格式的才会添加前缀,而index.html的类型是text/html,所以是不会添加的。
后来我查看了/usr/local/nginx/conf/mime.types文件才发现,如下
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/x-javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
......
}
必须要是txt的文件,才会服务器的相应中的Content-Type设置为text/plain。
所以解决办法就是:
要使得浏览器访问的是txt的文件。
在/usr/local/nginx/html/文件下建立一个123.txt文件,然而让浏览器去访问这份文件,就能够得到我们新添加的http过滤模块发挥的功能,在原有123.txt文件的基础上添加了字段:[my filter prefix]。如下图所示: