Nginx模块开发 从url变量中读取内容并显示
这是由前面的一个最简单的例子修改而成的。
前面的例子是从配置文件中读取内容,并显示。
这个例子是从url变量中读取内容并显示。
?
?
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
?
static char* ngx_echo_readconf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void* ngx_echo_create_loc_conf(ngx_conf_t *cf);
static char* ngx_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
ngx_int_t ngx_http_hi_module_init(ngx_conf_t *cf);
?
typedef struct {
?? ?ngx_str_t ecdata;
?? ?ngx_flag_t ? ? ? ? ? enable;
} ngx_echo_loc_conf_t;
?
// 读取配置文件内容 echo -> ecdata
// 1、ngx_echo_readconf是程序第一步
static ngx_command_t ?ngx_echo_commands[] = {
?? ?{ ngx_string("echo"),
?? ? ?NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
?? ? ?ngx_echo_readconf,
?? ? ?NGX_HTTP_LOC_CONF_OFFSET,
?? ? ?offsetof(ngx_echo_loc_conf_t, ecdata),
?? ? ?NULL },
?? ? ?ngx_null_command
};
?
?
static ngx_http_module_t ?ngx_echo_module_ctx = {
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* preconfiguration */
?? ?ngx_http_hi_module_init, ? ? ? ? ? /* postconfiguration 从配置文件中读取key定义 */
?
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* create main configuration */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* init main configuration */
?
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* create server configuration */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* merge server configuration */
?
?? ?ngx_echo_create_loc_conf, ?/* create location configuration */
?? ?ngx_echo_merge_loc_conf /* merge location configuration */
};
?
//////////////////////
// ? ? 定义模块 ? ? ? ? ? ? ?//
//////////////////////
ngx_module_t ?ngx_http_hi_module = {
?? ?NGX_MODULE_V1,
?? ?&ngx_echo_module_ctx, /* module context */
?? ?ngx_echo_commands, ? /* module directives */
?? ?NGX_HTTP_MODULE, ? ? ? ? ? ? ? /* module type */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* init master */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* init module */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* init process */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* init thread */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* exit thread */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* exit process */
?? ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ?/* exit master */
?? ?NGX_MODULE_V1_PADDING
};
?
// 获得URL参数
static ngx_int_t ?ngx_http_key_index;
static ngx_str_t ?ngx_http_key_value = ngx_string("key");
ngx_http_variable_value_t ? ? ?*key_vv;
?
static ngx_int_t
ngx_http_hi_module_variable_not_found(ngx_http_request_t *r,
?? ? ? ?ngx_http_variable_value_t *v, uintptr_t data)
{
?? ?v->not_found = 1;
?? ?return NGX_OK;
}
?
static ngx_int_t
ngx_http_hi_module_add_variable(ngx_conf_t *cf, ngx_str_t *name) {
?? ?ngx_http_variable_t ? ? ? ? *v;
?
?? ?v = ngx_http_add_variable(cf, name, NGX_HTTP_VAR_CHANGEABLE);
?? ?if (v == NULL) {
?? ? ? ?return NGX_ERROR;
?? ?}
?
?? ?v->get_handler = ngx_http_hi_module_variable_not_found;
?
?? ?return ngx_http_get_variable_index(cf, name);
}
?
?
//////////////////////
// ? ? 主要的处理函数
//////////////////////
static ngx_int_t
ngx_echo_handler(ngx_http_request_t *r)
{
?? ?printf("called:ngx_echo_handler\n");
?
?? ?////////////////////////////////////////////
?? ?// ? ? ? ?读取URL里面具体的key变量的值
?? ?////////////////////////////////////////////
?? ?key_vv = ngx_http_get_indexed_variable(r,
?? ?ngx_http_key_index);
?
// ? ?printf("read URL key idx:%d\n",ngx_http_key_index);
// ? ?printf("read URL key:%s\n",key_vv->data);
?
?? ?ngx_int_t ? ? rc;
?? ?ngx_buf_t ? ?*b;
?? ?ngx_chain_t ? out;
?
?? ?ngx_echo_loc_conf_t ?*cglcf;
?? ?cglcf = ngx_http_get_module_loc_conf(r, ngx_http_hi_module);
?
// 限制请求的方法
?? ?if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
?? ? ? ?return NGX_HTTP_NOT_ALLOWED;
?? ?}
?? ?if (r->headers_in.if_modified_since) {
?? ? ? ?return NGX_HTTP_NOT_MODIFIED;
?? ?}
?
?? ?r->headers_out.content_type.len = sizeof("text/html") - 1;
?? ?r->headers_out.content_type.data = (u_char *) "text/html";
?
?
?
?? ?r->headers_out.status = NGX_HTTP_OK; // 发送状态码
// ? ?r->headers_out.content_length_n = cglcf->ecdata.len;
?? ?r->headers_out.content_length_n = key_vv->len; // 发送内容长度
?? ?if (r->method == NGX_HTTP_HEAD) {
?? ? ? ?rc = ngx_http_send_header(r);
?
?? ? ? ?if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
?? ? ? ? ? ?return rc;
?? ? ? ?}
?? ?}
?
?? ?b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
?? ?if (b == NULL) {
?? ?ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
?? ? ? ?return NGX_HTTP_INTERNAL_SERVER_ERROR;
?? ?}
?
?? ?////////////////////////////////////////////
?? ?// ? ? ? 定义输出
?? ?////////////////////////////////////////////
?? ?out.buf = b;
?? ?out.next = NULL;
?
?
// ? ?b->pos = cglcf->ecdata.data;
// ? ?b->last = cglcf->ecdata.data+(cglcf->ecdata.len);
?? ?////////////////////////////////////////////
?? ?// ? ? ? 给输出复制
?? ?////////////////////////////////////////////
?? ?b->pos = key_vv->data;
?? ?b->last = key_vv->data+(key_vv->len);
?
?? ?b->memory = 1;
?? ?b->last_buf = 1;
?? ?rc = ngx_http_send_header(r);
?
?? ?if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
?? ? ? ?return rc;
?? ?}
?? ?return ngx_http_output_filter(r, &out); // 交给过滤器
}
?
//////////////////////
// ? ? 读取配置 echo
//////////////////////
static char *
ngx_echo_readconf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
?? ?printf("called:ngx_echo_readconf\n");
?? ?ngx_http_core_loc_conf_t ?*clcf;
?
?? ?clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
?? ?clcf->handler = ngx_echo_handler; // 2、主要的处理函数:ngx_echo_handler是程序第二步
?? ?ngx_conf_set_str_slot(cf,cmd,conf);
?
?? ?return NGX_CONF_OK;
}
?
?
static void *
ngx_echo_create_loc_conf(ngx_conf_t *cf)
{
?? ?printf("called:ngx_echo_create_loc_conf\n");
?? ?ngx_echo_loc_conf_t ?*conf;
?
?? ?conf = ngx_pcalloc(cf->pool, sizeof(ngx_echo_loc_conf_t));
?? ?if (conf == NULL) {
?? ? ? ?return NGX_CONF_ERROR;
?? ?}
?
?? ?conf->ecdata.len=0;
?? ?conf->ecdata.data=NULL;
?? ?conf->enable = NGX_CONF_UNSET;
?? ?return conf;
}
static char *
ngx_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
?? ?printf("called:ngx_echo_merge_loc_conf\n");
?? ?ngx_echo_loc_conf_t *prev = parent;
?? ?ngx_echo_loc_conf_t *conf = child;
?
?? ?ngx_conf_merge_str_value(conf->ecdata, prev->ecdata, 10);
?? ?ngx_conf_merge_value(conf->enable, prev->enable, 0);
?
?? ?return NGX_CONF_OK;
}
?
//////////////////////
// 从配置文件中读取key定义
//////////////////////
ngx_int_t
ngx_http_hi_module_init(ngx_conf_t *cf)
{
?? ?printf("called:ngx_http_hi_module_init\n");
?
?? ?// 读key参数
?? ?if ((ngx_http_key_index = ngx_http_hi_module_add_variable(
?? ? ? ? ? ? ? ?cf, &ngx_http_key_value)) == NGX_ERROR)
?? ?{
?? ? ? ?return NGX_ERROR;
?? ?}
?
?? ?return NGX_OK;
?
}
?
?
下面是配置文件
worker_processes ?1;
daemon off;?
master_process ?off;
error_log ?/tmp/error.log debug;
pid /tmp/nginx_demo.pid;
events {
?? ?worker_connections ?1024;
}
http {
?? ?#include ? ? ? /etc/nginx/mime.types;
?? ?sendfile ? ? ? ?on;
?? ?keepalive_timeout ?65;
?? ?tcp_nodelay ? ? ? ?on;
?? ?server {
?? ? ? ?listen ? 8100;
?? ? ? ?server_name ?localhost;
?? ? ? ?access_log ?/tmp/access.log;
?? ? ? ?error_log ?/tmp/error.log debug;
?? ? ? ?location /hello {
?? ? ? ? ? ?set $key $arg_key;
?? ? ? ? ? ?echo "abcd";
?? ? ? ?}
?? ?}
}
?
?
访问方法
?
http://10.1.6.100:8100/hello?key=012sadf
?
?
?