nginx:将自己编写HTTP过滤模块融入nginx时遇到的问题

来源:互联网 发布:网络营业执照查询 编辑:程序博客网 时间:2024/06/05 03:50

缘由

今天看了 深入理解Nginx 第6章,看懂了书之后,利用了书上的代码自己测试了一下。测试的过程居然有点艰难,虽然最后还是完成了功能。但是还是暴露出两点:
  1. 自己的基础知识不扎实
  2. 书中有些部分不严谨
当然,现在发现这些是值得庆幸的,因为这使的我能够早日学到更多知识。
所以这篇博客主要是我在阅读完成第六章之后,做实验过程中遇到的问题,而不是将http过滤模块讲清楚。

实验过程

从书的作者的blog下载第六章实例代码,
  • http://taohui.org.cn/ 的右边侧栏
这份代码里面包含了这份例子模块的代码(ngx_http_myfilter_module.c),还有config文件(用于标识这份代码的一些信息,在执行./configure命令会使用到,能够确定这份代码的用途),还是一份nginx.conf的配置文件(这份配置问题有问题,至少不严禁)

然后解压
为了将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. 使用方式可以指定配置文件的位置,
  2. 也可以选择把默认的配置文件的位置给覆盖掉。
然后,运行,那么我们会得到一个403权限不允许的页面。
之后就困然了我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;
那么,该浏览器就会去访问/usr/local/nginx/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]。如下图所示:


chrome查看http的响应和请求

如下图所示,可以让我们request和response的信息。


总结

多的就不说了,主要就是基础不扎实。另外关于过滤模块还是有很多知识,有兴趣的朋友直接看书,书上我感觉逻辑写的非常清晰。
0 0
原创粉丝点击