好久没顾这个了,最近比较清闲,重新拾掇一下,有始有终。
回到正题,前一篇介绍完了请求的处理,先面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,以便于您获取更多的相关知识。