内容简介:NGINX 开发指南
简介
-
代码结构
-
头文件
-
整数
-
常用返回值
-
错误处理
字符串
-
概述
-
格式化
-
数值转换
-
正则表达式
时间
容器
-
数组
- 列表
-
队列
-
红黑树
-
哈希
内存管理
-
堆
-
内存池
-
共享内存
日志
周期
缓冲
网络
-
连接
事件
-
事件
-
I/O 事件
-
定时器事件
-
延迟事件
- 遍历事件
进程
线程
模块
-
添加新模块
-
核心模块
-
配置指令
HTTP
-
连接
-
请求
-
配置
-
阶段
-
变量
-
复杂值
-
请求重定向
-
子请求
-
请求结束
-
请求体
-
响应
-
响应体
-
响应体过滤
-
构建过滤模块
-
缓冲重用
-
负载均衡
代码布局
-
auto — 构建脚本
-
src
-
unix
-
win32
-
modules — 其他HTTP模块
-
v2 — HTTPv2
-
modules — 事件通知模块:epoll, kqueue, select 等
-
core — 基本类型和函数 — string, array, log, pool 等
-
event — event内核
-
http — HTTP内核模块和通用代码
-
mail — mail模块
-
os — 平台相关代码
-
stream — 流相关模块
每个 nginx 文件都应该在开始的时候包含下面两个文件:
#include <ngx_config.h> #include <ngx_core.h>
除此之外,HTTP 相关的代码应该包含
#include <ngx_http.h>
邮件相关代码应该包含
#include <ngx_mail.h>
流相关代码应该包含
#include <ngx_stream.h>
整数
一般情况下,nginx代码使用如下两个整数类型: ngx_int_t
和 ngx_uint_t
,分别用typedef定义成了 intptr_t
和 uintptr_t
。
常用返回值
nginx中的大多数函数使用如下类型的返回值:
-
NGX_OK — 处理成功
-
NGX_ERROR — 处理失败
-
NGX_AGAIN — 处理未完成,函数需要被再次调用
-
NGX_DECLINED — 处理被拒绝,例如相关功能在配置文件中被关闭。不要将此当成错误。
-
NGX_BUSY — 资源不可用
-
NGX_DONE — 处理完成或者在他处继续处理。也可以作为处理成功使用。
-
NGX_ABORT — 函数终止。也可以作为处理出错的返回值。
错误处理
为了获取最近一次系统错误码,nginx提供了ngx_errno宏。该宏被映射到了POSIX平台的errno变量上,而在Windows平台中,则变为对GetLastError()的函数调用。为了获取最近一次socket错误码,nginx提供了ngx_socket_errno宏。同样,在POSIX平台上该宏被映射为errno变量,而在Windows环境中则是对WSAGetLastError()进行调用。考虑到对性能的影响,ngx_errno和ngx_socket_errno不应该被连续访问。如果有连续、频繁访问的需要,则应该将错误码的值存储到类型为ngx_err_t的本地变量中,然后使用本地变量进行访问。如果需要设置错误码,可以使用ngx_set_errno(errno)和ngx_set_socket_errno(errno)这两个宏。
ngx_errno和ngx_socket_errno变量可以在调用日志相关函数ngx_log_error()和ngx_log_debugX()的时候使用,这样具体的错误文本就会被添加到日志输出中。
一个使用ngx_errno的例子:
void
ngx_my_kill(ngx_pid_t pid, ngx_log_t *log, int signo)
{
ngx_err_t err;
if (kill(pid, signo) == -1) {
err = ngx_errno;
ngx_log_error(NGX_LOG_ALERT, log, err, "kill(%P, %d) failed", pid, signo);
if (err == NGX_ESRCH) {
return 2;
}
return 1;
}
return 0;
}
字符串
概述
nginx使用无符号的char类型指针来表示C字符串:u_char *。
nginx字符串类型ngx_str_t的定义如下所示:
typedef struct {
size_t len;
u_char *data;
} ngx_str_t;
结构体成员len存放字符串的长度,成员data指向字符串本身数据。在ngx_str_t中存放的字符串,对于超出len长度的部分可以是NULL结尾('\0'——译者注),也可以不是。在大多数情况是不以NULL结尾的。然而,在nginx的某些代码中(例如解析配置的时候),ngx_str_t中的字符串是以NULL结尾的吗,这种情况会使得字符串比较变得更加简单,也使得使用系统调用的时候更加容易。
nginx提供了一系列关于字符串处理的函数。它们在src/core/ngx_string.h文件中定义。其中的一部分就是对C库中字符串函数的封装:
-
ngx_strcmp()
-
ngx_strncmp()
-
ngx_strstr()
-
ngx_strlen()
-
ngx_strchr()
-
ngx_memcmp()
-
ngx_memset()
-
ngx_memcpy()
-
ngx_memmove()
还有一些nginx特有的字符串函数:
-
ngx_memzero() 内存清0
-
ngx_cpymem() 和ngx_memcpy()行为类似,不同的是该函数返回的是copy后的最终目的地址,这在需要连续拼接多个字符串的场景下很方便。
-
ngx_movemem() 和ngx_memmove()的行为类似,不同的是该函数返回的是move后的最终目的地址。
-
ngx_strlchr() 在字符串中查找一个特定字符,字符串由两个指针界定。
最后是一些大小写转换和字符串比较的函数:
-
ngx_tolower()
-
ngx_toupper()
-
ngx_strlow()
-
ngx_strcasecmp()
-
ngx_strncasecmp()
格式化
nginx提供了一些格式化字符串的函数。以下这些函数支持nginx特有的类型:
-
ngx_sprintf(buf, fmt, ...)
-
ngx_snprintf(buf, max, fmt, ...)
-
ngx_slpintf(buf, last, fmt, ...)
-
ngx_vslprint(buf, last, fmt, args)
-
ngx_vsnprint(buf, max, fmt, args)
这些函数支持的全部格式化选项定义在src/core/ngx_string.c文件中,以下是其中的一部分:
%O — off_t %T — time_t %z — size_t %i — ngx_int_t %p — void * %V — ngx_str_t * %s — u_char * (null-terminated) %*s — size_t + u_char *
'u'修饰符将类型指明为无符号,'X'和'x'则将输出转换为16禁止。
例如:
u_char buf[NGX_INT_T_LEN]; size_t len; ngx_int_t n; /* set n here */ len = ngx_sprintf(buf, "%ui", n) — buf;
数值转换
nginx实现了若干用于数值转换的函数:
-
ngx_atoi(line, n) — 将一个指定长度的字符串转换为一个正整数,类型为ngx_int_t。出错返回NGX_ERROR。
-
ngx_atosz(line, n) — 同上,转换类型为ssize_t
-
ngx_atoof(line, n) — 同上,转换类型为off_t
-
ngx_atotm(line, n) — 同上,转换类型为time_t
-
ngx_atofp(line, n, point) — 将一个固定长度的定点小数字符串转换为ngx_int_t类型的正整数。转换结果会左移point指定的10进制位数。字符串中的定点小数不能含有多过point参数指定的小数位。出错返回NGX_ERROR。举例:ngx_atofp("10.5", 4, 2) 返回1050
-
ngx_hextoi(line, n) — 将表示16进制正整数的字符串转换为ngx_int_t类型的整数。出错返回NGX_ERROR。
正则表达式
nginx中的正则表达式接口是对PCRE库的封装。相关的头文件是src/core/ngx_regex.h。
要使用正则表达式进行字符串匹配,首先需要对正则表达式进行编译,这通常是在配置解析阶段处理的。需要注意的是,因为PCRE的支持是可选的,因此所有使用正则相关接口的代码都需要用NGX_PCRE括起来:
#if (NGX_PCRE)
ngx_regex_t *re;
ngx_regex_compile_t rc;
u_char errstr[NGX_MAX_CONF_ERRSTR];
ngx_str_t value = ngx_string("message (\\d\\d\\d).*Codeword is '(?<cw>\\w+)'");
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
rc.pattern = value;
rc.pool = cf->pool;
rc.err.len = NGX_MAX_CONF_ERRSTR;
rc.err.data = errstr;
/* rc.options are passed as is to pcre_compile() */
if (ngx_regex_compile(&rc) != NGX_OK) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
return NGX_CONF_ERROR;
}
re = rc.regex;
#endif
编译成功之后,结构体ngx_regex_compile_t的captures和named_captures成员分别会被填上正则表达式中全部以及命名捕获的数量。
然后,编译过的正则表达式就可以用来进行字符串匹配:
ngx_int_t n;
int captures[(1 + rc.captures) * 3];
ngx_str_t input = ngx_string("This is message 123. Codeword is 'foobar'.");
n = ngx_regex_exec(re, &input, captures, (1 + rc.captures) * 3);
if (n >= 0) {
/* string matches expression */
} else if (n == NGX_REGEX_NO_MATCHED) {
/* no match was found */
} else {
/* some error */
ngx_log_error(NGX_LOG_ALERT, log, 0, ngx_regex_exec_n " failed: %i", n);
}
ngx_regex_exec()的参数有:编译了的正则表达式re,待匹配的字符串s,可选的用于存放发现的捕获和其大小的整数数组。捕获数组的大小必须是3的倍数,这是PCRE库的API要求的。在上面例子中,该数组的大小是通过总捕获数加上字符串自身来计算得出的。
现在,如果成功匹配,则可以对捕获进行访问:
u_char *p;
size_t size;
ngx_str_t name, value;
/* all captures */
for (i = 0; i < n * 2; i += 2) {
value.data = input.data + captures[i];
value.len = captures[i + 1] — captures[i];
}
/* accessing named captures */
size = rc.name_size;
p = rc.names;
for (i = 0; i < rc.named_captures; i++, p += size) {
/* capture name */
name.data = &p[2];
name.len = ngx_strlen(name.data);
n = 2 * ((p[0] << 8) + p[1]);
/* captured value */
value.data = &input.data[captures[n]];
value.len = captures[n + 1] — captures[n];
}
ngx_regex_exec_array()函数接受ngx_regex_elt_t元素的数组(其实就是多个编译好的正则表达式以及对应的名字),一个待匹配字符串以及一个log。该函数会对待匹配字符串逐一应用数组中的正则表达式,直到匹配成功或者无一匹配。存在成功的匹配则返回NGX_OK,否则返回NGX_DECLINED,出错返回NGX_ERROR。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 网站图标开发指南
- WalletConnect 非权威开发指南
- 2019 简易Web开发指南
- SlimPHP开发指南五:请求
- linux 内核开发指南 - 2 开发流程
- 积木 Sketch 插件进阶开发指南
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First JavaScript Programming
Eric T. Freeman、Elisabeth Robson / O'Reilly Media / 2014-4-10 / USD 49.99
This brain-friendly guide teaches you everything from JavaScript language fundamentals to advanced topics, including objects, functions, and the browser’s document object model. You won’t just be read......一起来看看 《Head First JavaScript Programming》 这本书的介绍吧!