Nginx-请求处理与响应

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 > 1) {

        /*
         * 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, 0) != 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 = 0; i < port->naddrs - 1; i++) {
                if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
                    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 = 0; i < port->naddrs - 1; 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[0].conf;
            break;
#endif

        default: /* AF_INET */
            addr = port->addrs;
            hc->addr_conf = &addr[0].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, 0,
                          "no \"ssl_certificate\" is defined "
                          "in server listening on SSL port");
            ngx_http_close_connection(c);
            return;
        }

        hc->ssl = 1;

        rev->handler = ngx_http_ssl_handshake;
    }
    }
#endif

    if (hc->addr_conf->proxy_protocol) {
        hc->proxy_protocol = 1;
        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, 1);

    if (ngx_handle_read_event(rev, 0) != 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, 0,
                   "http process request line");
     //超时直接返回
    if (rev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        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, 0,
                           "http request line: \"%V\"", &r->request_line);

            r->method_name.len = r->method_end - r->request_start + 1;
            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, 0);

                if (rc == NGX_DECLINED) {
                    ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                  "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 == 0
                    && 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, 20,
                              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, 0,
                          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, 1);

            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, 0,
                              "client sent too long URI");
                ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
                return;
            }
        }
    }
}
时间: 2024-10-13 23:28:44

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

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

最近用了nodejs搭建服务器,然后用了nginx做了反向代理,项目开发需求,没办法.但是发现了经过代理之后发现网页请求变慢了,而且是不能忍的一分钟以上. 一开始,怀疑是在nodejs那边的问题,结果在nodejs那边进行了判断(通过写测试代码),但是发现是经过了一分多钟请求才到nodejs这边,那么只能先排除nodejs这方面的问题. 那么要排除nginx的问题,我的环境是 windows7(x64) nginx(1.62)  nodejs(4.23),配置如下 server { listen

nginx代理 修改响应内容

最近接手一个问题 在每次出现404的情况时:需要在响应的内容中,添加 request_uri  remote_ip  等一些内容. 开始的时候 发现一个模块  --with-http_sub_module 可以对响应内容进行一个替换修改 但是这个模块需要从新对nginx进行编译,在编译的时候添加模块 --prefix=/usr/local/nginx --with-http_sub_module 然后就可以在nginx.conf中使用了 sub_filter  thisisatestipaddr

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

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

nginx 定义:响应头和请求头

1) 响应头 add_header 例如: add_header Cache-Control no-cache; add_header Access-Control-Allow-Origin *; add_header X-Proxy-Cache $upstream_cache_status; 要小心Nginx的add_header指令详解: 当当前层级中没有add_header指令才会继承父级设置.所以我的疑问就清晰了:location中有add_header,nginx.conf中的配置被丢

nginx 替换网站响应内容(ngx_http_sub_module)

nginx在编译安装的时候需要编译安装这个模块 --with-http_sub_module make && make install 语法:     sub_filter old_string new_string;默认值:     -配置段:     http, server, location 这三个段都可以配置sub_filter 设置需要使用说明字符串替换说明字符串.old_string是要被替换的字符串,new_string是新的字符串,它里面可以带变量. 语法:       

025.ASP.NET概念、请求处理与响应

ASP.NET 1. 技术: html js css 是用于做网页的技术 2. 网页: 可以用浏览器浏览的页面(通常HTML格式) 网站: 是网页的集合 WebSite 3. 使用IIS搭建web站点,放置网页的集合,供公共用户访问才可以. 右键->计算机->管理->服务器和应用程序->Internet(IIS) http://localhost/动画练习.htm 4. 机器地址: IP,每台电脑都有唯一的IP地址,使用ipconfig查看 端口号: port,IP相当于公司总机,

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

93 一个非常重要的指令 proxy_buffer_size 指令限制头部响应header最大值 proxy_buffering 指令主要是指 上游服务器是否接受完完整包体在处理 默认是on 也就是接收完后再处理 proxy_buffers 指令 是指 如果包体大小超过设置大小 则向磁盘写入该包体 否则就不写入 proxy_max_temp_file_size 指令是指 限制包体写入磁盘最大值 proxy_temp_file_write_size 指令是指每次写入磁盘大小 proxy_temp_

zabbix监控nginx性能状态

nginx在生产环境中的应用越来越广泛,所以需要对nginx的性能状态做一些监控,来发现出来出现的问题.nginx处理流程图具体如下: 注释:Accepts(接受).Handled(已处理).Requests(请求数)是一直在增加的计数器.Active(活跃).Waiting(等待).Reading(读).Writing(写)随着请求量而增减 名称 描述 指标类型 Accepts(接受) NGINX 所接受的客户端连接数 资源: 功能 Handled(已处理) 成功的客户端连接数 资源: 功能

nginx源码分析--模块分类

ngx-modules Nginx 主要的模块大致可以分为四类: handler – 协同完成客户端请求的处理.产生响应数据.比如模块, ngx_http_rewrite_module, ngx_http_log_module, ngx_http_static_module. filter – 对 handler 产生的响应数据做各种过滤处理.比如模块, ngx_http_not_modified_filter_module, ngx_http_header_filter_module. ups

Nginx学习.md

正常运行的必备配置 user Syntax: user user [group]; Default: user nobody nobody; Context: main 指定运行worker进程的用户 和组. pid Syntax: pid file; Default: pid nginx.pid; Context: main 指定nginx的pid文件: worker_rlimit_nofile Syntax: worker_rlimit_nofile number; Default: - C