2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
// core.ngx_core.h
typedef struct ngx_module_s ngx_module_t;
// core.ngx_module.h
struct ngx_module_s {
/* 表示当前模块在这个模块中的序号,
* 既表示模块的优先级,也表明模块的位置,
* 借以帮助Nginx框架快速获得某个模块的数据
*/
ngx_uint_t ctx_index;
/*
* 表示当前模块在ngx_modules数组中的序号,
* ctx_index表示当前模块在一类模块中的序号,
* index是在所有模块中的序号
*/
ngx_uint_t index;
// 模块名称
char *name;
// spare系列的保留变量
ngx_uint_t spare0;
ngx_uint_t spare1;
// 模块的版本号
ngx_uint_t version;
const char *signature; //
/*
* 用于指向一类模块的上下文结构体,
* Nginx模块有很多种类的模块,不同模块之间功能差距很大
* 事件类型的模块主要处理IO事件,HTTP类型模块主要处理HTTP应用层的功能
* ctx指向特定类型模块的公共接口,例如HTTP模块中,指向ngx_http_module_t
*/
void *ctx;
ngx_command_t *commands;// 将处理nginx.conf中的配置项
/*
* 模块的类型,有5种
* NGX_HTTP_MODULE,NGX_CORE_MODULE,NGX_CONF_MODULE,NGX_EVENT_MODULE,NGX_MALL_MODULE
* 实际上可以自己定义类型
* */
ngx_uint_t type;
/*
* 如下7个函数指针表示有7个执行点会分别调用这7个方法,对于任何一个方法
* 如果不需要Nginx在某个时刻执行它,那么可以简单的设置为NULL空指针即可
* */
// 当master进程启动时进行回调init_master,但是目前为止,框架代码从来不会调用,设置为NULL
ngx_int_t (*init_master)(ngx_log_t *log);
// init_module初始化所有模块时被调用,在master/worker模式下,这个阶段将在启动worker子进程前完成
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
// 在正常服务前被调用,在master/worker模式下,多个worker子进程已经产生,在每个worker进程的初始化过程会调用所有模块的init_process
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
// Nginx不支持多线程模式,所以init_thread在框架代码中没有被调用过,设置为NULL
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
// exit_thread也不支持,设置为NULL
void (*exit_thread)(ngx_cycle_t *cycle);
// 在服务停止前调用,master/worker模式下,worker进程会在退出前调用它
void (*exit_process)(ngx_cycle_t *cycle);
// 在master进程退出前被调用
void (*exit_master)(ngx_cycle_t *cycle);
/*
* 以下8个变量也是保留字段,目前没有使用,但可用Nginx提供的NGX_MODULE_V1_PADDING宏来填充
* */
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
Bei der Definition des HTTP-Moduls wird der Typ auf NGX_HTTP_MODULE gesetzt. Für die Rückrufmethoden: init_module, init_process, exit_process, exit_master werden sie vom Nginx-Code aufgerufen und haben nichts mit dem HTTP-Framework zu tun. Auch wenn http{...} ist in nginx.conf nicht definiert, diese Art der Öffnung Für HTTP-Funktionskonfigurationselemente werden diese Zerstörungsmethoden weiterhin aufgerufen. Daher werden sie bei der Entwicklung von HTTP-Modulen normalerweise auf NULL gesetzt. Wenn sie nicht als Webserver verwendet werden, wird kein Code im HTTP-Modul ausgeführt.
Bei der Definition des HTTP-Moduls müssen als letztes die beiden Mitglieder ctx und commands festgelegt werden. Bei Modulen vom Typ HTTP verweist ctx auf die Schnittstelle ngx_http_module_t.
// http.ngx_http_config.h
typedef struct {
// 解析配置文件前被调用
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
// 完成配置文件的解析后调用
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
//当需要创建数据结构用于存储main级别的全局配置项时,可以通过create_main_conf回调方法创建存储全局配置项的结构体
void *(*create_main_conf)(ngx_conf_t *cf);
// 常用与初始化main级别配置项
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
// 当需要创建数据结构用于存储srv级别的配置项时,可以通过create_srv_conf回调方法创建存储srv级别配置项的结构体
void *(*create_srv_conf)(ngx_conf_t *cf);
// 合并main级别和srv级别的同名配置项
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
// 当需要创建结构体用于存储loc级别的配置项时,可以实现create_loc_conf回调方法
void *(*create_loc_conf)(ngx_conf_t *cf);
// 合并srv级别和loc级别下的同名配置项
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
Die Aufrufreihenfolge der oben genannten acht Phasen unterscheidet sich von der definierten Reihenfolge. Während des Nginx-Startvorgangs kann die tatsächliche Reihenfolge, in der das HTTP-Framework diese Rückrufmethoden aufruft, wie folgt aussehen: (bezogen auf das Konfigurationselement nginx.conf).
1) Hauptconf erstellen
2) create_srv_conf (erstellen_srv_conf)
3) create_loc_conf
4)Vorkonfiguration
5) init_main_conf
6) merge_srv_conf
7) merge_loc_conf
8) Nachkonfiguration
Das Befehlsarray wird verwendet, um die Konfigurationsdateiparameter des Moduls zu definieren. Das Ende des Arrays wird durch ngx_null_command dargestellt. Wenn Nginx ein Konfigurationselement analysiert, werden zunächst alle Module kompiliert Mit anderen Worten: Wenn ngx_null_command im Array erkannt wird, verwendet das aktuelle Modul das aktuelle Modul nicht mehr zum Parsen des Konfigurationselements.
// core.ngx_core.h
typedef struct ngx_command_s ngx_command_t;
// core.ngx_conf_file.h
struct ngx_command_s {
ngx_str_t name;// 配置项名称,列入:gzip
ngx_uint_t type;// 配置项类型,指定可以出现的位置,例如server,location中以及它可以携带的参数个数
// 出现了name中指定的配置项后,将会调用set方法处理配置项的参数
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
// 在配置文件中的偏移量
ngx_uint_t conf;
// 通常用于预设的解析方法解析配置项
ngx_uint_t offset;
// 配置项读取后的处理方法,必须是ngx_conf_post_t结构体指针
void *post;
};
#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL }
// http.modules.ngx_http_mytest_module.c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
static char *ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_http_mytest_commands[] = {
{
ngx_string("mytest"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS,
ngx_http_mytest,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
static ngx_http_module_t ngx_http_mytest_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_mytest_module = {
NGX_MODULE_V1,
&ngx_http_mytest_module_ctx, /* module context */
ngx_http_mytest_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
};
static char *ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_mytest_handler;
return NGX_CONF_OK;
}
// http.ngx_http_core_module.h
typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t;
struct ngx_http_core_loc_conf_s {
ngx_str_t name; /* location name */
ngx_str_t escaped_name;
#if (NGX_PCRE)
ngx_http_regex_t *regex;
#endif
unsigned noname:1; /* "if () {}" block or limit_except */
unsigned lmt_excpt:1;
unsigned named:1;
unsigned exact_match:1;
unsigned noregex:1;
unsigned auto_redirect:1;
#if (NGX_HTTP_GZIP)
unsigned gzip_disable_msie6:2;
unsigned gzip_disable_degradation:2;
#endif
ngx_http_location_tree_node_t *static_locations;
#if (NGX_PCRE)
ngx_http_core_loc_conf_t **regex_locations;
#endif
/* pointer to the modules' loc_conf */
void **loc_conf;
uint32_t limit_except;
void **limit_except_loc_conf;
ngx_http_handler_pt handler;
/* location name length for inclusive location with inherited alias */
size_t alias;
ngx_str_t root; /* root, alias */
ngx_str_t post_action;
ngx_array_t *root_lengths;
ngx_array_t *root_values;
ngx_array_t *types;
ngx_hash_t types_hash;
ngx_str_t default_type;
off_t client_max_body_size; /* client_max_body_size */
off_t directio; /* directio */
off_t directio_alignment; /* directio_alignment */
size_t client_body_buffer_size; /* client_body_buffer_size */
size_t send_lowat; /* send_lowat */
size_t postpone_output; /* postpone_output */
size_t sendfile_max_chunk; /* sendfile_max_chunk */
size_t read_ahead; /* read_ahead */
size_t subrequest_output_buffer_size;
/* subrequest_output_buffer_size */
ngx_http_complex_value_t *limit_rate; /* limit_rate */
ngx_http_complex_value_t *limit_rate_after; /* limit_rate_after */
ngx_msec_t client_body_timeout; /* client_body_timeout */
ngx_msec_t send_timeout; /* send_timeout */
ngx_msec_t keepalive_time; /* keepalive_time */
ngx_msec_t keepalive_timeout; /* keepalive_timeout */
ngx_msec_t lingering_time; /* lingering_time */
ngx_msec_t lingering_timeout; /* lingering_timeout */
ngx_msec_t resolver_timeout; /* resolver_timeout */
ngx_msec_t auth_delay; /* auth_delay */
ngx_resolver_t *resolver; /* resolver */
time_t keepalive_header; /* keepalive_timeout */
ngx_uint_t keepalive_requests; /* keepalive_requests */
ngx_uint_t keepalive_disable; /* keepalive_disable */
ngx_uint_t satisfy; /* satisfy */
ngx_uint_t lingering_close; /* lingering_close */
ngx_uint_t if_modified_since; /* if_modified_since */
ngx_uint_t max_ranges; /* max_ranges */
ngx_uint_t client_body_in_file_only; /* client_body_in_file_only */
ngx_flag_t client_body_in_single_buffer;
/* client_body_in_singe_buffer */
ngx_flag_t internal; /* internal */
ngx_flag_t sendfile; /* sendfile */
ngx_flag_t aio; /* aio */
ngx_flag_t aio_write; /* aio_write */
ngx_flag_t tcp_nopush; /* tcp_nopush */
ngx_flag_t tcp_nodelay; /* tcp_nodelay */
ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */
ngx_flag_t absolute_redirect; /* absolute_redirect */
ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */
ngx_flag_t port_in_redirect; /* port_in_redirect */
ngx_flag_t msie_padding; /* msie_padding */
ngx_flag_t msie_refresh; /* msie_refresh */
ngx_flag_t log_not_found; /* log_not_found */
ngx_flag_t log_subrequest; /* log_subrequest */
ngx_flag_t recursive_error_pages; /* recursive_error_pages */
ngx_uint_t server_tokens; /* server_tokens */
ngx_flag_t chunked_transfer_encoding; /* chunked_transfer_encoding */
ngx_flag_t etag; /* etag */
#if (NGX_HTTP_GZIP)
ngx_flag_t gzip_vary; /* gzip_vary */
ngx_uint_t gzip_http_version; /* gzip_http_version */
ngx_uint_t gzip_proxied; /* gzip_proxied */
#if (NGX_PCRE)
ngx_array_t *gzip_disable; /* gzip_disable */
#endif
#endif
#if (NGX_THREADS || NGX_COMPAT)
ngx_thread_pool_t *thread_pool;
ngx_http_complex_value_t *thread_pool_value;
#endif
#if (NGX_HAVE_OPENAT)
ngx_uint_t disable_symlinks; /* disable_symlinks */
ngx_http_complex_value_t *disable_symlinks_from;
#endif
ngx_array_t *error_pages; /* error_page */
ngx_path_t *client_body_temp_path; /* client_body_temp_path */
ngx_open_file_cache_t *open_file_cache;
time_t open_file_cache_valid;
ngx_uint_t open_file_cache_min_uses;
ngx_flag_t open_file_cache_errors;
ngx_flag_t open_file_cache_events;
ngx_log_t *error_log;
ngx_uint_t types_hash_max_size;
ngx_uint_t types_hash_bucket_size;
ngx_queue_t *locations;
#if 0
ngx_http_core_loc_conf_t *prev_location;
#endif
};
typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
// http.ngx_http_request.h
#define NGX_HTTP_CONTINUE 100
#define NGX_HTTP_SWITCHING_PROTOCOLS 101
#define NGX_HTTP_PROCESSING 102
#define NGX_HTTP_OK 200
#define NGX_HTTP_CREATED 201
#define NGX_HTTP_ACCEPTED 202
#define NGX_HTTP_NO_CONTENT 204
#define NGX_HTTP_PARTIAL_CONTENT 206
#define NGX_HTTP_SPECIAL_RESPONSE 300
#define NGX_HTTP_MOVED_PERMANENTLY 301
#define NGX_HTTP_MOVED_TEMPORARILY 302
#define NGX_HTTP_SEE_OTHER 303
#define NGX_HTTP_NOT_MODIFIED 304
#define NGX_HTTP_TEMPORARY_REDIRECT 307
#define NGX_HTTP_PERMANENT_REDIRECT 308
#define NGX_HTTP_BAD_REQUEST 400
#define NGX_HTTP_UNAUTHORIZED 401
#define NGX_HTTP_FORBIDDEN 403
#define NGX_HTTP_NOT_FOUND 404
#define NGX_HTTP_NOT_ALLOWED 405
#define NGX_HTTP_REQUEST_TIME_OUT 408
#define NGX_HTTP_CONFLICT 409
#define NGX_HTTP_LENGTH_REQUIRED 411
#define NGX_HTTP_PRECONDITION_FAILED 412
#define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE 413
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
#define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415
#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416
#define NGX_HTTP_MISDIRECTED_REQUEST 421
#define NGX_HTTP_TOO_MANY_REQUESTS 429
/* Our own HTTP codes */
/* The special code to close connection without any response */
#define NGX_HTTP_CLOSE 444
#define NGX_HTTP_NGINX_CODES 494
#define NGX_HTTP_REQUEST_HEADER_TOO_LARGE 494
#define NGX_HTTPS_CERT_ERROR 495
#define NGX_HTTPS_NO_CERT 496
/*
* We use the special code for the plain HTTP requests that are sent to
* HTTPS port to distinguish it from 4XX in an error page redirection
*/
#define NGX_HTTP_TO_HTTPS 497
/* 498 is the canceled code for the requests with invalid host name */
/*
* HTTP does not define the code for the case when a client closed
* the connection while we are processing its request so we introduce
* own code to log such situation when a client has closed the connection
* before we even try to send the HTTP header to it
*/
#define NGX_HTTP_CLIENT_CLOSED_REQUEST 499
#define NGX_HTTP_INTERNAL_SERVER_ERROR 500
#define NGX_HTTP_NOT_IMPLEMENTED 501
#define NGX_HTTP_BAD_GATEWAY 502
#define NGX_HTTP_SERVICE_UNAVAILABLE 503
#define NGX_HTTP_GATEWAY_TIME_OUT 504
#define NGX_HTTP_VERSION_NOT_SUPPORTED 505
#define NGX_HTTP_INSUFFICIENT_STORAGE 507
Zusätzlich zu den in der RFC2616-Spezifikation definierten Rückgabecodes umfassen die oben genannten Rückgabewerte auch von Nginx selbst definierte HTTP-Rückgabecodes. Beispiel: NGX_HTTP_CLOSE wird verwendet, um das HTTP-Framework aufzufordern, die Benutzerverbindung direkt zu schließen.
Nginx全局定义的错误码
// core.ngx_core.h
#define NGX_OK 0
#define NGX_ERROR -1
#define NGX_AGAIN -2
#define NGX_BUSY -3
#define NGX_DONE -4
#define NGX_DECLINED -5
#define NGX_ABORT -6
Wenn ngx_http_output_filter schließlich aufgerufen wird, um ein Antwortpaket an den Benutzer zu senden, kann der Rückgabewert von ngx_http_output_filter als Rückgabewert der Methode ngx_http_mytest_handler verwendet werden.
// http.ngx_http.h
typedef struct ngx_http_request_s ngx_http_request_t;
// http.ngx_http_request.h
struct ngx_http_request_s {
...
ngx_uint_t method;
ngx_uint_t http_version;
ngx_str_t request_line;
ngx_str_t uri;
ngx_str_t args;
ngx_str_t exten;
ngx_str_t unparsed_uri;
ngx_str_t method_name;
ngx_str_t http_protocol;
ngx_str_t schema;
...
u_char *uri_start;
u_char *uri_end;
u_char *uri_ext;
u_char *args_start;
u_char *request_start;
u_char *request_end;
u_char *method_end;
u_char *schema_start;
u_char *schema_end;
...
}
// http.ngx_http_request.h
ngx_uint_t method;
// http.ngx_http_request.h
#define NGX_HTTP_UNKNOWN 0x00000001
#define NGX_HTTP_GET 0x00000002
#define NGX_HTTP_HEAD 0x00000004
#define NGX_HTTP_POST 0x00000008
#define NGX_HTTP_PUT 0x00000010
#define NGX_HTTP_DELETE 0x00000020
#define NGX_HTTP_MKCOL 0x00000040
#define NGX_HTTP_COPY 0x00000080
#define NGX_HTTP_MOVE 0x00000100
#define NGX_HTTP_OPTIONS 0x00000200
#define NGX_HTTP_PROPFIND 0x00000400
#define NGX_HTTP_PROPPATCH 0x00000800
#define NGX_HTTP_LOCK 0x00001000
#define NGX_HTTP_UNLOCK 0x00002000
#define NGX_HTTP_PATCH 0x00004000
#define NGX_HTTP_TRACE 0x00008000
#define NGX_HTTP_CONNECT 0x00010000
So erhalten Sie die Methode
ngx_str_t uri;
ngx_str_t unparsed_uri;
u_char *uri_start;
u_char *uri_end;
u_char *uri_ext;
uri stellt den URI in der Anfrage dar, und uri_start und uri_end können ebenfalls abgerufen werden.
Die Mitgliedsvariable exten zeigt auf die vom Benutzer angeforderte Dateierweiterung.
unparsed_uri stellt die ursprüngliche Anfrage ohne URL-Dekodierung dar. Wenn uri beispielsweise /ab ist, ist unparsed_uri /a%20b
args verweist auf die URL-Parameter in der Benutzeranfrage. Ebenso können args_start und uri_end auch die URL abrufen
Das Datenelement von http_protocol zeigt auf die HTTP-Protokollversionszeichenfolge in der Benutzeranforderung, und das Len-Element ist die Länge der Protokollversionszeichenfolge.
http_version ist die von Nginx analysierte Protokollversion
ngx_uint_t http_version;
#define NGX_HTTP_VERSION_9 9
#define NGX_HTTP_VERSION_10 1000
#define NGX_HTTP_VERSION_11 1001
#define NGX_HTTP_VERSION_20 2000
#define NGX_HTTP_VERSION_30 3000
Es wird empfohlen, http_version zur Analyse der HTTP-Protokollversion zu verwenden.
Verwenden Sie request_start und request_end, um die ursprüngliche Benutzeranforderungszeile abzurufen
struct ngx_http_request_s {
...
ngx_buf_t *header_in;
ngx_http_headers_in_t headers_in;
...
}
header_in verweist auf den von Nginx empfangenen ungeparsten HTTP-Header. header_in ist ein Puffer, der HTTP-Header akzeptiert.
// http.ngx_http_request.h
typedef struct {
//所有解析过的HTTP头部都在headers链表中
ngx_list_t headers;
// 每个ngx_table_elt_t成员都是RFC2616规范定义的HTTP头部,
// 它们实际上指向headers链表中相应成员,当为NULL时表示没有解析到相应的HTTP头部
ngx_table_elt_t *host;
ngx_table_elt_t *connection;
ngx_table_elt_t *if_modified_since;
ngx_table_elt_t *if_unmodified_since;
ngx_table_elt_t *if_match;
ngx_table_elt_t *if_none_match;
ngx_table_elt_t *user_agent;
ngx_table_elt_t *referer;
ngx_table_elt_t *content_length;
ngx_table_elt_t *content_range;
ngx_table_elt_t *content_type;
ngx_table_elt_t *range;
ngx_table_elt_t *if_range;
ngx_table_elt_t *transfer_encoding;
ngx_table_elt_t *te;
ngx_table_elt_t *expect;
ngx_table_elt_t *upgrade;
#if (NGX_HTTP_GZIP || NGX_HTTP_HEADERS)
ngx_table_elt_t *accept_encoding;
ngx_table_elt_t *via;
#endif
ngx_table_elt_t *authorization;
ngx_table_elt_t *keep_alive;
#if (NGX_HTTP_X_FORWARDED_FOR)
ngx_table_elt_t *x_forwarded_for;
#endif
#if (NGX_HTTP_REALIP)
ngx_table_elt_t *x_real_ip;
#endif
#if (NGX_HTTP_HEADERS)
ngx_table_elt_t *accept;
ngx_table_elt_t *accept_language;
#endif
#if (NGX_HTTP_DAV)
ngx_table_elt_t *depth;
ngx_table_elt_t *destination;
ngx_table_elt_t *overwrite;
ngx_table_elt_t *date;
#endif
ngx_table_elt_t *cookie;
// 只有ngx_http_auth_basic_module才会用到的成员
ngx_str_t user;
ngx_str_t passwd;
// server名称
ngx_str_t server;
// 计算出的HTTP包体大小(ngx_table_elt_t * content_length)
off_t content_length_n;
time_t keep_alive_n;
// HTTP连接类型,取值范围是0,
// #define NGX_HTTP_CONNECTION_CLOSE 1
//#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2
unsigned connection_type:2;
unsigned chunked:1;
unsigned multi:1;
unsigned multi_linked:1;
// 以下7个标志位是 HTTP框架根据浏览器传来的useragent头部,可以判断浏览器的类型,只为1表示相应的浏览器发来的请求
unsigned msie:1;
unsigned msie6:1;
unsigned opera:1;
unsigned gecko:1;
unsigned chrome:1;
unsigned safari:1;
unsigned konqueror:1;
} ngx_http_headers_in_t;
Beispiel: So finden Sie ungewöhnliche HTTP-Anforderungsheader. Sie können nur headers_in.headers durchlaufen
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) {
...
ngx_list_part_t *part = &r->header_in.headers.part;
ngx_table_elt_t *header = part->elts;
for (i = 0;; ++i) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
header = part->elts;
i = 0;
}
if (header[i].hash == 0){
continue;
}
if (0 == ngx_strncasecmp(header[i].key.data,(u_char*) "Rpc-Description",header[i].key.len)){
if (0 == ngx_strncmp(header[i].value.data,"uploadFile",header[i].value.len)){
// 找到了正确的头,继续向下执行
}
}
}
...
}
Die Länge des HTTP-Paketkörpers kann sehr groß sein. Wenn Sie versuchen, alle Paketkörper auf einmal aufzurufen und zu lesen, blockiert dies wahrscheinlich den Nginx-Prozess. Das HTTP-Framework bietet eine asynchrone Methode zum Empfangen des Paketkörpers.
ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
ngx_http_client_body_handler_pt post_handler);
Dies ist eine asynchrone Methode. Der Aufruf kann nur anzeigen, dass Nginx mit der Annahme des angeforderten Paketkörpers beginnen muss. Er zeigt nicht an, ob der gesamte Inhalt des Paketkörpers angenommen wurde zurückgerufen werden.
Die Antwort besteht aus drei Teilen: Antwortzeile, Antwortheader und Pakettext.
ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
struct ngx_http_request_s {
ngx_http_headers_out_t headers_out;
}
typedef struct {
ngx_list_t headers;
ngx_list_t trailers;
ngx_uint_t status;
ngx_str_t status_line;
ngx_table_elt_t *server;
ngx_table_elt_t *date;
ngx_table_elt_t *content_length;
ngx_table_elt_t *content_encoding;
ngx_table_elt_t *location;
ngx_table_elt_t *refresh;
ngx_table_elt_t *last_modified;
ngx_table_elt_t *content_range;
ngx_table_elt_t *accept_ranges;
ngx_table_elt_t *www_authenticate;
ngx_table_elt_t *expires;
ngx_table_elt_t *etag;
ngx_table_elt_t *cache_control;
ngx_table_elt_t *link;
ngx_str_t *override_charset;
size_t content_type_len;
ngx_str_t content_type;
ngx_str_t charset;
u_char *content_type_lowcase;
ngx_uint_t content_type_hash;
off_t content_length_n;
off_t content_offset;
time_t date_time;
time_t last_modified_time;
} ngx_http_headers_out_t;
Anforderungsheader hinzufügen
ngx_table_elt_t h = ngx_list_push(&r->headers_out.headers);
if (h == NULL){
return NGX_ERROR
}
h.hash = 1;
h.key.len = sizeof("TestHeader") - 1;
h.key.data = (u_char *) "TestHeader";
h.value.len = sizeof("TestValue") - 1;
h.value.data = (u_char *) "TestValue" ;
ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
Senden Sie den HTTP-Antworttext an den Client
ngx_buf_t *b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
b->start = (u_char*)ngx_pcalloc(r->pool,128);
b->pos = b->start;
b->last = b->start;
b->end = b->last + 128;
b->temporary = 1;
// 等同于如下
ngx_buf_t *b = ngx_create_temp_buf(r->pool,128)
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) {
// 必须为GET或者HEAD,否则返回405
if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))){
return NGX_HTTP_NOT_ALLOWED;
}
// 丢弃请求中的包体
ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK){
return rc;
}
// 设置返回类型
ngx_str_t type = ngx_string("text/plain");
// 设置返回体
ngx_str_t response = ngx_string("Hello World!");
// 设置响应码
r->headers_out.status = NGX_HTTP_OK;
// 设置响应体大小
r->headers_out.content_length_n = response.len;
// 设置类型
r->headers_out.content_type = type;
// 发送HTTP头部
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only){
return rc;
}
// 构造ngx_buf_t结构体发送包体
ngx_buf_t *b;
b = ngx_create_temp_buf(r->pool,response.len);
if (b == NULL){
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
// 将hello world复制到ngx_buf_t指向的内存中
ngx_memcpy(b->pos,response.data,response.len);
// 注意设置好last指针
b->last = b->pos + response.len;
// 声明这是最后一块缓冲区
b->last_buf = 1;
// 构造发送时的ngx_chain_t结构体
ngx_chain_t out;
out.buf = b;
out.next = NULL;
// 发送包体
return ngx_http_output_filter(r,&out);
}
Setzen Sie in_file von ngx_buf_t auf 1, um anzuzeigen, dass der Puffer eine Datei und kein Speicher ist. Die Datei ist ngx_file_t, die Struktur ist wie folgt:
struct ngx_file_s {
ngx_fd_t fd;// 文件句柄描述符
ngx_str_t name;// 文件名称
ngx_file_info_t info;// 文件大小等基本信息,就是Linux系统定义的stat结构
off_t offset;// 表示处理到文件何处了
off_t sys_offset;// 当前文件系统偏移量
ngx_log_t *log;// 日志对象,相关的日志会输出到log指定的日志文件中
#if (NGX_THREADS || NGX_COMPAT)
ngx_int_t (*thread_handler)(ngx_thread_task_t *task,
ngx_file_t *file);
void *thread_ctx;
ngx_thread_task_t *thread_task;
#endif
#if (NGX_HAVE_FILE_AIO || NGX_COMPAT)
ngx_event_aio_t *aio;
#endif
unsigned valid_info:1;
unsigned directio:1;// 在发送大文件时可以设置为1
};