void ngx_http_init_connection(ngx_connection_t *c)
{
ngx_uint_t i;
ngx_event_t *rev;
struct sockaddr_in *sin;
ngx_http_port_t *port;
ngx_http_in_addr_t *addr;
ngx_http_log_ctx_t *ctx;
ngx_http_connection_t *hc;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
ngx_http_in6_addr_t *addr6;
#endif hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
//申请内存
if (hc == NULL) {
ngx_http_close_connection(c);
return;
} c->data = hc; /* find the server configuration for the address:port */ port = c->listening->servers;
//监听套接口上有多个目的IP
if (port->naddrs > ) { /*
* there are several addresses on this port and one of them
* is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
* is required to determine a server address
*/ if (ngx_connection_local_sockaddr(c, NULL, ) != NGX_OK) {
ngx_http_close_connection(c);
return;
} switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) c->local_sockaddr; addr6 = port->addrs; /* the last address is "*" */ for (i = ; i < port->naddrs - ; i++) {
if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, ) == ) {
break;
}
} hc->addr_conf = &addr6[i].conf; break;
#endif default: /* AF_INET */
sin = (struct sockaddr_in *) c->local_sockaddr; addr = port->addrs; /* the last address is "*" */ for (i = ; i < port->naddrs - ; i++) {
if (addr[i].addr == sin->sin_addr.s_addr) {
break;
}
} hc->addr_conf = &addr[i].conf; break;
} } else { switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6)
case AF_INET6:
addr6 = port->addrs;
hc->addr_conf = &addr6[].conf;
break;
#endif default: /* AF_INET */
addr = port->addrs;
hc->addr_conf = &addr[].conf;
break;
}
} /* the default server configuration for the address:port */
hc->conf_ctx = hc->addr_conf->default_server->ctx;
//当监听套接口只有一个目的IP时,将该地址上的server设置为默认server
//还会有后续处理0
ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
if (ctx == NULL) {
ngx_http_close_connection(c);
return;
} ctx->connection = c;
ctx->request = NULL;
ctx->current_request = NULL; c->log->connection = c->number;
c->log->handler = ngx_http_log_error;
c->log->data = ctx;
c->log->action = "waiting for request"; c->log_error = NGX_ERROR_INFO; rev = c->read;
rev->handler = ngx_http_wait_request_handler;
c->write->handler = ngx_http_empty_handler; #if (NGX_HTTP_V2)
if (hc->addr_conf->http2) {
rev->handler = ngx_http_v2_init;
}
#endif #if (NGX_HTTP_SSL)
//https 的SSL加密
{
ngx_http_ssl_srv_conf_t *sscf; sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); if (sscf->enable || hc->addr_conf->ssl) { c->log->action = "SSL handshaking"; if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, c->log, ,
"no \"ssl_certificate\" is defined "
"in server listening on SSL port");
ngx_http_close_connection(c);
return;
} hc->ssl = ; rev->handler = ngx_http_ssl_handshake;
}
}
#endif if (hc->addr_conf->proxy_protocol) {
hc->proxy_protocol = ;
c->log->action = "reading PROXY protocol";
} if (rev->ready) {
/* the deferred accept(), iocp */
//accept()接受服务端的请求后将请求数据已经准备好了,然后着手处理
if (ngx_use_accept_mutex) {
//有加锁 将事件对象加入ngx_posted_events链表中 然后释放锁 释放锁后在处理事件
ngx_post_event(rev, &ngx_posted_events);
return;
}
//没有假如事件监控机制中,是因为当所有的请求数据都已经到达后 读取数据处理请求然后响应即可,没有必要再加
//入事件监控机制中,如果加入了 什么作用都没有起到,然后在删除 做的都是无用功
rev->handler(rev);
return;
}
//recv->ready == 0加入超时管理机制和事件监控机制中
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_reusable_connection(c, ); if (ngx_handle_read_event(rev, ) != NGX_OK) {
ngx_http_close_connection(c);
return;
} }

请求处理

函数ngx_http_process_line()处理的数据就是从客户端发送过来的http请求头中的Request_Line。分为三步 1.读取Request_line数据,2.解析Request_line 3.存储解析结果并设置相关值

第一步:读取Request_Line数据。通过函数ngx_http_read_request_header()将数据存储到r->header_in中。

第二步:解析Request_Line。将读取到的Request_Line数据进行解析的工作实现在ngx_http_process_request_line()中

第三步:存储解析结果并设置相关值。在Request_Line的解析过程中会有一些赋值操作,但更多的是在成功解析后。

static void ngx_http_process_request_line(ngx_event_t *rev)
{
ssize_t n;
ngx_int_t rc, rv;
ngx_str_t host;
ngx_connection_t *c;
ngx_http_request_t *r; c = rev->data;
r = c->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, ,
"http process request line");
//超时直接返回
if (rev->timedout) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
c->timedout = ;
ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
return;
} rc = NGX_AGAIN;
//解析数据
for ( ;; ) { if (rc == NGX_AGAIN) {
n = ngx_http_read_request_header(r);
//读取数据
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
}
// 解析数据 存储解析结果 将解析结果存储在 r->header_in 中
rc = ngx_http_parse_request_line(r, r->header_in);
//解析成功
if (rc == NGX_OK) { /* the request line has been parsed successfully */ r->request_line.len = r->request_end - r->request_start;
r->request_line.data = r->request_start;
r->request_length = r->header_in->pos - r->request_start; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, ,
"http request line: \"%V\"", &r->request_line); r->method_name.len = r->method_end - r->request_start + ;
r->method_name.data = r->request_line.data; if (r->http_protocol.data) {
r->http_protocol.len = r->request_end - r->http_protocol.data;
} if (ngx_http_process_request_uri(r) != NGX_OK) {
return;
} if (r->host_start && r->host_end) { host.len = r->host_end - r->host_start;
host.data = r->host_start; rc = ngx_http_validate_host(&host, r->pool, ); if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_INFO, c->log, ,
"client sent invalid host in request line");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
} if (rc == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
} if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
return;
} r->headers_in.server = host;
} if (r->http_version < NGX_HTTP_VERSION_10) { if (r->headers_in.server.len ==
&& ngx_http_set_virtual_server(r, &r->headers_in.server)
== NGX_ERROR)
{
return;
} ngx_http_process_request(r);
return;
} if (ngx_list_init(&r->headers_in.headers, r->pool, ,
sizeof(ngx_table_elt_t))
!= NGX_OK)
{
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
} c->log->action = "reading client request headers"; rev->handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev); return;
} if (rc != NGX_AGAIN) { /* there was error while a request line parsing */ ngx_log_error(NGX_LOG_INFO, c->log, ,
ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
} /* NGX_AGAIN: a request line parsing is still incomplete */ if (r->header_in->pos == r->header_in->end) { rv = ngx_http_alloc_large_header_buffer(r, ); if (rv == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
} if (rv == NGX_DECLINED) {
r->request_line.len = r->header_in->end - r->request_start;
r->request_line.data = r->request_start; ngx_log_error(NGX_LOG_INFO, c->log, ,
"client sent too long URI");
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
return;
}
}
}
}

Nginx-请求处理与响应的更多相关文章

  1. 【Nginx】发送响应

    请求处理完毕后,需要向用户发送http响应,告知客户端Nginx的执行结果.http响应主要包括响应行.响应头部.包体三部分.发送http响应时需要执行发送http头部(发送http头部时也会发送响应 ...

  2. nodejs 通过nginx后出现响应慢的解决方法

    最近用了nodejs搭建服务器,然后用了nginx做了反向代理,项目开发需求,没办法.但是发现了经过代理之后发现网页请求变慢了,而且是不能忍的一分钟以上. 一开始,怀疑是在nodejs那边的问题,结果 ...

  3. 修改nginx的http响应头server字段

    信息泄露类型:HTTP服务器响应头Server字段信息泄露 示例: 解决: 需要重新对nginx编译安装: [root@localhost ~]# tar zxvf nginx-1.8.1.tar.g ...

  4. 【Nginx】修改响应头,根据不同请求IP重定向到不同IP

    背景: 使用CAS登录的过程中会涉及到三次重定向,如果在同一个局域网内,是没有任何问题的,但如果涉及到跨网访问,这个问题就比较蛋疼了. 解决思路: 通过Nginx对要访问的系统进行代理,根据请求IP来 ...

  5. 高性能Web服务器Nginx的配置与部署研究(3)Nginx请求处理机制

    1. 处理什么样的请求 处理访问到 Nginx 所在 IP 地址的请求,并且这些请求的 HTTP 头信息中的 Host 为所要处理的域名(如下以80端口为例),如下几个 server 就对应响应的请求 ...

  6. Nginx请求处理流程

    因为 Nginx 运行在企业内网的最外层也就是边缘节点,那么他处理的的流量是其他应用服务器处理流量的数倍,甚至几个数量级,我们知道任何一种问题在不同的数量级下,他的解决方案是完全不同的,所以在 Ngi ...

  7. Nginx学习笔记(三):Nginx 请求处理

    Request Nginx 中的 ngx_http_request_t 是对一个 http 请求的封装: 一个 http 请求包含:请求行.请求头.请求体,响应行.响应头.响应体 Nginx 处理请求 ...

  8. nginx 定义:响应头和请求头

    1) 响应头 add_header 例如: add_header Cache-Control no-cache; add_header Access-Control-Allow-Origin *; a ...

  9. Nginx配置各种响应头防止XSS,点击劫持,frame恶意攻击

    为什么要配置HTTP响应头? 不知道各位有没有被各类XSS攻击.点击劫持 (ClickJacking. frame 恶意引用等等方式骚扰过,百度联盟被封就有这些攻击的功劳在里面.为此一直都在搜寻相关防 ...

  10. Nginx 如何处理上游响应的数据

    陶辉93 一个非常重要的指令 proxy_buffer_size 指令限制头部响应header最大值 proxy_buffering 指令主要是指 上游服务器是否接受完完整包体在处理 默认是on 也就 ...

随机推荐

  1. AOJ.176 两数组最短距离 (乱搞题)

    两数组最短距离 点我挑战题目 题意分析 给出2个数组,让求出2个数组元素差的绝对值的最小值是多少. 我这里是o(m+n)的算法.首先对于第一个数组,让他的第一个元素和第二个元素比较,如果他的第一个元素 ...

  2. 项目管理---git----快速使用git笔记(三)------coding.net注册和新建项目(远程仓库)

    我们在第一章已经了解了github和coding.net的区别: github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开. codin ...

  3. nodejs路径处理方法和绝对路径

    1. 路径处理方法 __dirname 表示当前文件所在的目录的绝对路径__filename 表示当前文件的绝对路径module.filename ==== __filename 等价process. ...

  4. 差点AFO

    差点就AFO了,小伙伴们一定注意护眼啊. 眼睛总算是活过来了. 还有一个月联赛,加油

  5. [LeetCode] Sort Colors 对于元素取值有限的数组,只遍历一遍的排序方法

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  6. Fiddler进行模拟POST、PUT提交数据注意点

    1.请求头要加 Accept: application/xml Content-Type: application/json 2.地址栏url地址后不要忘记加“/” 3.POST和PUT的对象参数都是 ...

  7. 【转】IOS版本自定义字体步骤

    本文转载自:http://quick.cocoachina.com/wiki/doku.php?id=ios%E7%89%88%E6%9C%AC%E4%BD%BF%E7%94%A8%E8%87%AA% ...

  8. 使用abp的 redis cache

    top 使用abp的 redis cache -1. 在微软维护的github项目的release里找到redis的windows版本 64位 大约5M,安装,安装,然后在安装目录找到redis.wi ...

  9. ajax post请求json数据在spring-controller解析

    1.前端post请求数据: userInfo=[{"id":"5","uname":"小李","phone&q ...

  10. 基于springmvc静态文件资源配置问题

    1.在这里只教大家一种非常实用的 比较简单的一种: 如果两种都配置记得注释掉这种: