在源碼中,用於http 頭部檢測的是 httpd_got_request 函數
該函數並沒有檢測頭部的內容,只是檢測頭部的格式而已,最明顯的格式檢測就是 \r\n ,空格,tab符 ,即http協議中,頭部的每一行都用 \r\n 結尾,在行中,每一詞用空格或tab符分開 ,說明更簡單一些,就是檢查請求行是不是有三個words,頭部結束是不是以空行結束 。僅此而已
下面是用的幾種狀態來檢測格式是否合法的
/* Checks hc->read_buf to see whether a complete request has been read so far; ** either the first line has two words (an HTTP/0.9 request), or the first ** line has three words and there's a blank line present. ** ** hc->read_idx is how much has been read in; hc->checked_idx is how much we ** have checked so far; and hc->checked_state is the current state of the ** finite state machine. */int httpd_got_request(httpd_conn* hc) {char c;for (; hc->checked_idx < hc->read_idx; ++hc->checked_idx) {c = hc->read_buf[hc->checked_idx];switch (hc->checked_state) {case CHST_FIRSTWORD://the first word "GET"switch (c) {case ' ':case '\t':hc->checked_state = CHST_FIRSTWS;break;case '\012':case '\015':hc->checked_state = CHST_BOGUS;return GR_BAD_REQUEST;}break;case CHST_FIRSTWS:switch (c) {case ' ':case '\t':break;case '\012':case '\015':hc->checked_state = CHST_BOGUS;return GR_BAD_REQUEST;default:hc->checked_state = CHST_SECONDWORD;break;}break;case CHST_SECONDWORD:switch (c) {case ' ':case '\t':hc->checked_state = CHST_SECONDWS;break;case '\012':case '\015':/* The first line has only two words - an HTTP/0.9 request. */return GR_GOT_REQUEST;}break;case CHST_SECONDWS:switch (c) {case ' ':case '\t':break;case '\012':case '\015':hc->checked_state = CHST_BOGUS;return GR_BAD_REQUEST;default:hc->checked_state = CHST_THIRDWORD;break;}break;case CHST_THIRDWORD:switch (c) {case ' ':case '\t':hc->checked_state = CHST_THIRDWS;break;case '\012':hc->checked_state = CHST_LF;break;case '\015':hc->checked_state = CHST_CR;break;}break;case CHST_THIRDWS:switch (c) {case ' ':case '\t':break;case '\012':hc->checked_state = CHST_LF;break;case '\015':hc->checked_state = CHST_CR;break;default:hc->checked_state = CHST_BOGUS;return GR_BAD_REQUEST;}break;case CHST_LINE:switch (c) {case '\012':hc->checked_state = CHST_LF;break;case '\015':hc->checked_state = CHST_CR;break;}break;case CHST_LF:switch (c) {case '\012':/* Two newlines in a row - a blank line - end of request. */return GR_GOT_REQUEST;case '\015':hc->checked_state = CHST_CR;break;default:hc->checked_state = CHST_LINE;break;}break;case CHST_CR:switch (c) {case '\012':hc->checked_state = CHST_CRLF;break;case '\015':/* Two returns in a row - end of request. */return GR_GOT_REQUEST;default:hc->checked_state = CHST_LINE;break;}break;case CHST_CRLF:switch (c) {case '\012':/* Two newlines in a row - end of request. */return GR_GOT_REQUEST;case '\015':hc->checked_state = CHST_CRLFCR;break;default:hc->checked_state = CHST_LINE;break;}break;case CHST_CRLFCR:switch (c) {case '\012':case '\015':/* Two CRLFs or two CRs in a row - end of request. */return GR_GOT_REQUEST;default:hc->checked_state = CHST_LINE;break;}break;case CHST_BOGUS:return GR_BAD_REQUEST;}}return GR_NO_REQUEST;}