Lighttpd1.4.20源码分析之状态机(3)返回response

好久没顾这个了,最近比较清闲,重新拾掇一下,有始有终。

回到正题,前一篇介绍完了请求的处理,先面lighttpd将会把处理的结果返回给客户端。状态机进入CON_STATE_RESPONST_START。在这个状态中,服务器主要的工作在函数connection_handle_write_prepare。这个函数不算复杂,主要是根据客户端请求的method来设置response的headers,其实就是设置“Content-Length”的值。下面是函数代码,做了一些删减:

  1 static int connection_handle_write_prepare(server * srv, connection * con)  2 {  3    if (con->mode == DIRECT)  4    {  5        /*  6         * static files  7         */  8        switch (con->request.http_method)  9        { 10        case HTTP_METHOD_GET: 11        case HTTP_METHOD_POST: 12        case HTTP_METHOD_HEAD: 13        case HTTP_METHOD_PUT: 14        case HTTP_METHOD_MKCOL: 15        case HTTP_METHOD_DELETE: 16        case HTTP_METHOD_COPY: 17        case HTTP_METHOD_MOVE: 18        case HTTP_METHOD_PROPFIND: 19        case HTTP_METHOD_PROPPATCH: 20        case HTTP_METHOD_LOCK: 21        case HTTP_METHOD_UNLOCK: 22            break; 23        case HTTP_METHOD_OPTIONS: 24            /* 25             * 400 is coming from the request-parser BEFORE uri.path is set 26             * 403 is from the response handler when noone else catched it 27             * */ 28            if ((!con->http_status || con->http_status == 200) 29                && con->uri.path->used && con->uri.path->ptr[0] != '*') 30            { 31                response_header_insert(srv, con, CONST_STR_LEN("Allow"), 32                   CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); 33  34                con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED; 35                con->parsed_response &= ~HTTP_CONTENT_LENGTH; 36  37                con->http_status = 200; 38                con->file_finished = 1; 39  40                chunkqueue_reset(con->write_queue); 41            } 42            break; 43        default: 44            switch (con->http_status) 45            { 46            case 400:            /* bad request */ 47            case 414:            /* overload request header */ 48            case 505:            /* unknown protocol */ 49            case 207:            /* this was webdav */ 50                break; 51            default: 52                con->http_status = 501; 53                break; 54            } 55            break; 56        } 57    } 58  59    if (con->http_status == 0) 60    { 61        con->http_status = 403; 62    } 63  64    switch (con->http_status) 65    { 66    case 204:                    /* class: header only */ 67    case 205: 68    case 304: 69        /* 70         * disable chunked encoding again as we have no body 71         */ 72        con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED; 73        con->parsed_response &= ~HTTP_CONTENT_LENGTH; 74        chunkqueue_reset(con->write_queue); 75  76        con->file_finished = 1; 77        break; 78    default:                    /* class: header + body */ 79        if (con->mode != DIRECT) 80            break; 81  82        /* 83         * only custom body for 4xx and 5xx 84         */ 85        if (con->http_status < 400 || con->http_status >= 600) 86            break; 87  88        con->file_finished = 0; 89        buffer_reset(con->physical.path); 90  91        /* 92         * try to send static errorfile 93         */ 94        if (!buffer_is_empty(con->conf.errorfile_prefix)) 95        { 96         //设置对应的错误提示文件 97        } 98  99        if (!con->file_finished)100        {101            //没有对应的错误提示文件,设置默认错误提示。102        }103        break;104    }105 106    if (con->file_finished)107    {108        /*109         * we have all the content and chunked encoding is not used, set a110         * content-length111         */112        if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&113            (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)114        {115            off_t qlen = chunkqueue_length(con->write_queue);116            /**117             * The Content-Length header only can be sent if we have content:118             * - HEAD doesn't have a content-body (but have a content-length)119             * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)120             *121             * Otherwise generate a Content-Length header as chunked encoding is not122             * available123             */124            if ((con->http_status >= 100 && con->http_status < 200) ||125                con->http_status == 204 || con->http_status == 304)126            {127                data_string *ds;128                /*129                 * no Content-Body, no Content-Length130                 */131                if (NULL != (ds = (data_string *) array_get_element(con->response.headers, "Content-Length")))132                {133                    buffer_reset(ds->value);    /* Headers with empty values134                                                 * are ignored for output */135                }136            }137            else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD)138            {139                /*140                 * qlen = 0 is important for Redirects (301, ...) as they MAY141                 * have a content. Browsers are waiting for a Content otherwise142                 */143                buffer_copy_off_t(srv->tmp_buf, qlen);144 145                response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));146            }147        }148    }149    else150    {151        /**152         * the file isn't finished yet, but we have all headers153         *154         * to get keep-alive we either need:155         * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or156         * - Transfer-Encoding: chunked (HTTP/1.1)157         */158 159        if (((con->parsed_response & HTTP_CONTENT_LENGTH) == 0) &&160            ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0))161        {162            con->keep_alive = 0;163        }164 165        /**166         * if the backend sent a Connection: close, follow the wish167         *168         * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we169         * will close the connection. That's fine. We can always decide the close170         * the connection171         *172         * FIXME: to be nice we should remove the Connection: ...173         */174        if (con->parsed_response & HTTP_CONNECTION)175        {176            /*177             * a subrequest disable keep-alive although the client wanted it178             */179            if (con->keep_alive && !con->response.keep_alive)180            {181                con->keep_alive = 0;182            }183        }184    }185 186    if (con->request.http_method == HTTP_METHOD_HEAD)187    {188        /**189         * a HEAD request has the same as a GET190         * without the content191         */192        con->file_finished = 1;193 194        chunkqueue_reset(con->write_queue);195        con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;196    }197 198    http_response_write_header(srv, con);199 200    return 0;201 }

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索break
, response
, connection reset
, case
, mage con
, status 129
, response status
, CON
, connection reset
, The
Chunked
lighttpd源码分析、lighttpd源码、lighttpd源码分析 pdf、lighttpd源码下载、lighttpd 1.4.35,以便于您获取更多的相关知识。

时间: 2024-12-02 12:10:39

Lighttpd1.4.20源码分析之状态机(3)返回response的相关文章

Lighttpd1.4.20源码分析之状态机(4) 错误处理和连接关闭

Lighttpd所要处理的错误分为两种.一种是http协议规定的错误,如404错误.另一种就是服务器运行过程中的错误,如write错误. 对于http协议规定的错误,lighttpd返回相应的错误提示文件.其实对于lighttpd而言,这不算错误.在返回错误提示文件后,相当于顺利的完成了一次请求,只是结果和客户端想要的不一样而已. 对于服务器运行中的错误,状态机会直接进入CON_STATE_ERROR状态.大部分的情况下,这种错误都是由客户端提前断开连接所造成的.比如你不停的刷新页面,在你刷新的

Lighttpd1.4.20源码分析之状态机(2)---通过状态机看连接处理1

前面大概的介绍了一下lighttpd的状态机.在这篇中,将通过状态机,看看lighttpd到底是怎样处理 连接请求的. 在本篇中,我们只介绍lighttpd的最基本功能──处理静态页面.lighttpd处理静态页面要使用 mod_staticfile.c插件.从名字中也可以看出是用来处理静态文件的.另外这个插件在配置文件中没有配 置,是lighttpd默认会加载的. 首先还是把状态机放这,以便查阅.

Lighttpd1.4.20源码分析之状态机(1)---状态机总览

前面讲了lighttpd的fdevent系统,从这一篇开始,我们将进入lighttpd的状态机.状态机可以说是lighttpd最核心的部分.lighttpd将一个连接在不同的时刻分成不同的状态,状态机则根据连接当前的状态,决定要对连接进行的处理以及下一步要进入的状态.下面这幅图描述了lighttpd的状态机:

lighttpd1.4.20源码分析 -工作模型

lighttpd的工作模型很简单──一个主进程加多个工作进程的多进程模型,也就是所谓的watcher-worker模型. 整个程序的入口(main函数)在server.c文件中.在main函数的开始部分必然是处理参数和各种繁杂的初始化工作.其中有两个地方要重点看一起.第一个是下面的语句: 1 if (test_config) //没有进行任何测试... 2 { 3 printf("Syntax OK\n"); 4 } 这个If语句是为了判断配置文件的语法是否合法.但是,明显,没有进行任

php源码分析之DZX1.5随机数函数random用法

  本文实例讲述了php源码分析之DZX1.5随机数函数random用法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php /** * @param int $length: 随机数长度 * @param int $numeric: 0或非0,其中0表示随机数由全数字组成,非0表示随机数由全字母组成 * @return string: 返回生成的随机数 */ function random($l

php源码分析之DZX1.5加密解密函数authcode用法

  本文实例讲述了php源码分析之DZX1.5加密解密函数authcode用法.分享给大家供大家参考.具体分析如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <?php $authkey

php源码分析之DZX1.5字符串截断函数cutstr用法

  本文实例讲述了php源码分析之DZX1.5字符串截断函数cutstr用法.分享给大家供大家参考.具体分析如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <?php /** * 函数来源DZX1.5,文件所在 /source/function/func

Spring AOP源码分析(八)SpringAOP要注意的地方

SpringAOP要注意的地方有很多,下面就举一个,之后想到了再列出来:  (1)SpringAOP对于最外层的函数只拦截public方法,不拦截protected和private方法,另外不会对最外层的public方法内部调用的其他方法也进行拦截,即只停留于代理对象所调用的方法.如下案例:  B类有两个public方法,foo1()和foo2(),foo1内部调用了foo2,简单如下:  ? 1 2 3 4 5 6 7 8 public void foo2() {          Syste

《深入理解SPARK:核心思想与源码分析》(第1章)

       自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售,欢迎感兴趣的同学购买.我开始研究源码时的Spark版本是1.2.0,经过7个多月的研究和出版社近4个月的流程,Spark自身的版本迭代也很快,如今最新已经是1.6.0.目前市面上另外2本源码研究的Spark书籍的版本分别是0.9.0版本和1.2.0版本,看来这些书的作者都与我一样,遇到了这种问