Nginx HTTP之请求行解析函数ngx_http_parse_request_line

╰+攻爆jí腚メ 2022-04-16 03:24 245阅读 0赞

Nginx的HTTP模块中使用ngx_http_parse_request_line函数来对读取的请求行进行解析,HTTP请求行的格式不是很复杂,但是要注意HTTP 0.9与1.0、1.1之间的区别;另外,作为Nginx的第一个版本,里面支持的请求方法也只有GET、POST和HEAD。

  1. /* http/ngx_http_parse.c */
  2. /* 解析HTTP请求行
  3. * param r: 待处理的HTTP请求
  4. * b: 存放请求行内容的缓冲区
  5. * return : 成功解析完整的请求行时返回NGX_OK;
  6. * 成功解析了部分请求行时返回NGX_AGAIN;
  7. * 否则返回其他
  8. */
  9. ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
  10. {
  11. // HTTP 0.9 请求行格式: [请求方法][空格..空格][URL](空格..空格)(回车符)[换行符]
  12. // HTTP >= 1.0 请求行格式: [请求方法][空格..空格][URL][空格..空格][协议版本][回车符][换行符]
  13. u_char ch, *p, *m;
  14. enum {
  15. sw_start = 0, // 初始状态
  16. sw_method, // 解析请求方法
  17. sw_space_after_method, // 解析请求方法后紧跟的一个空格
  18. sw_spaces_before_uri, // 解析URL前可能存在的多余空格
  19. sw_schema, // 解析schema(http/https)
  20. sw_schema_slash, // 解析<schema>:后紧跟的一个/
  21. sw_schema_slash_slash, // 解析<schema>:/后紧跟的一个/
  22. sw_host, // 解析<schema>://后紧跟的主机(域名/IP)
  23. sw_port, // 解析<schema>://<host>:后紧跟的端口
  24. sw_after_slash_in_uri, // 解析URL路径中/后的内容
  25. sw_check_uri, // ?
  26. sw_uri, // ?
  27. sw_http_09, // 解析URL后紧跟空格后的内容
  28. sw_http_H, // 解析协议版本的第二个字符T
  29. sw_http_HT, // 解析协议版本的第三个字符T
  30. sw_http_HTT, // 解析协议版本的第四个字符P
  31. sw_http_HTTP, // 解析协议版本的第五个字符/
  32. sw_first_major_digit, // 解析协议版本的主版本号的第一个数字
  33. sw_major_digit, // 解析协议版本的主版本号第一个数字后的数字或者.
  34. sw_first_minor_digit, // 解析协议版本的次版本号的第一个数字
  35. sw_minor_digit, // 解析协议版本的次版本号第一个数字后的数字
  36. sw_almost_done, // 解析结束的\n
  37. sw_done // 解析完成
  38. } state; // 枚举变量: HTTP请求行解析状态
  39. // 获取请求r的当前状态state
  40. state = r->state;
  41. // 获取缓冲区b的有效内容起始地址p
  42. p = b->pos;
  43. while (p < b->last && state < sw_done) {
  44. // p小于b->last时, 表明缓冲区内的有效内容不为空;
  45. // state小于sw_done, 表明未解析完成
  46. // ch指向缓冲区有效内容的第一个字符, p后移一位
  47. ch = *p++;
  48. switch (state) {
  49. /* HTTP methods: GET, HEAD, POST */
  50. case sw_start:
  51. // 当前状态为sw_start即起始状态
  52. // 置r->request_start为p-1, 也就是当前字符的位置
  53. r->request_start = p - 1;
  54. if (ch == CR || ch == LF) {
  55. // 如果当前字符为\r或者\n
  56. // 跳过
  57. break;
  58. }
  59. if (ch < 'A' || ch > 'Z') {
  60. // 如果当前字符不是大写字母
  61. // 请求方法必须是由大写字母组成的, 所以返回NGX_HTTP_PARSE_INVALID_METHOD,
  62. // 从字面上可以看出, 这个返回值表示无效的请求方法
  63. return NGX_HTTP_PARSE_INVALID_METHOD;
  64. }
  65. // 置state为sw_method, 表示解析请求方法
  66. state = sw_method;
  67. break;
  68. case sw_method:
  69. // 当前状态为解析请求方法
  70. if (ch == ' ') {
  71. // 如果当前字符为空格
  72. // 说明遇到了请求方法后面的空格了, p-2即为请求方法的最后一个字符
  73. // 置r->method_end为p-1, 记录请求方法的结束位置
  74. r->method_end = p - 1;
  75. // r->request_start此时指向的是请求方法的第一个字符
  76. m = r->request_start;
  77. if (r->method_end - m == 3) {
  78. // 如果请求方法子字符串的长度为3
  79. if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') {
  80. // 如果请求方法子字符串为GET
  81. // 置r->method为NGX_HTTP_GET
  82. r->method = NGX_HTTP_GET;
  83. }
  84. } else if (r->method_end - m == 4) {
  85. // 如果请求方法子字符串的长度为4
  86. if (m[0] == 'P' && m[1] == 'O'
  87. && m[2] == 'T' && m[3] == 'T')
  88. {
  89. // 如果请求方法子字符串为POST
  90. // 置r->method为NGX_HTTP_POST
  91. r->method = NGX_HTTP_POST;
  92. } else if (m[0] == 'H' && m[1] == 'E'
  93. && m[2] == 'A' && m[3] == 'D')
  94. {
  95. // 如果请求方法子字符串为HEAD
  96. // 置r->method为NGX_HTTP_HEAD
  97. r->method = NGX_HTTP_HEAD;
  98. }
  99. }
  100. // 解析完请求方法, 置state为sw_spaces_before_uri, 表示解析URL前面的空格
  101. // 因为此处已经解析到一个请求方法后的空格, 所以跳过状态sw_space_after_method,
  102. state = sw_spaces_before_uri;
  103. break;
  104. }
  105. if (ch < 'A' || ch > 'Z') {
  106. // 如果当前字符不是大写字母
  107. // 返回NGX_HTTP_PARSE_INVALID_METHOD
  108. return NGX_HTTP_PARSE_INVALID_METHOD;
  109. }
  110. break;
  111. case sw_space_after_method:
  112. // 当前状态为解析请求方法后紧跟的一个空格
  113. switch (ch) {
  114. case ' ':
  115. // 如果当前字符为空格
  116. // 置state为sw_spaces_before_uri, URL前面可能还有空格
  117. state = sw_spaces_before_uri;
  118. break;
  119. default:
  120. // 如果当前字符为非空格的字符
  121. // 请求方法和URL之间至少需要一个空格,
  122. // 返回NGX_HTTP_PARSE_INVALID_METHOD
  123. return NGX_HTTP_PARSE_INVALID_METHOD;
  124. }
  125. break;
  126. case sw_spaces_before_uri:
  127. // 当前状态为解析URL前可能存在的多余空格
  128. switch (ch) {
  129. case '/':
  130. // 如果当前字符为/, 说明遇到URL的第一个字符
  131. // 置r->uri_start为p-1, 记录URL的起始位置
  132. r->uri_start = p - 1;
  133. // 置state为sw_after_slash_in_uri, 表示解析URL路径中/后的内容
  134. state = sw_after_slash_in_uri;
  135. break;
  136. case ' ':
  137. // 如果当前字符为空格
  138. // 直接跳过
  139. break;
  140. default:
  141. if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
  142. // 如果当前字符为大小写字母, 说明遇到schema(http/https)的第一个字符了
  143. // 置r->schema_start为p-1, 记录schema的起始位置
  144. r->schema_start = p - 1;
  145. // 置state为sw_schema, 表示解析schema
  146. state = sw_schema;
  147. break;
  148. }
  149. // 当前字符为其他字符, 表示请求有误, 返回NGX_HTTP_PARSE_INVALID_REQUEST,
  150. // 即无效请求
  151. return NGX_HTTP_PARSE_INVALID_REQUEST;
  152. }
  153. break;
  154. case sw_schema:
  155. // 当前状态为解析schema
  156. switch (ch) {
  157. case ':':
  158. // 如果当前字符为:, 说明遇到schema的后一个字符了
  159. // 置r->schema_end为p-1, 记录schema的结束位置
  160. r->schema_end = p - 1;
  161. // 置state为sw_schema_slash, 表示解析<schema>:后紧跟的一个/
  162. state = sw_schema_slash;
  163. break;
  164. default:
  165. if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
  166. // 如果当前字符是大小写字符, 说明是我们想要的
  167. // 直接跳过
  168. break;
  169. }
  170. // 当前字符为其他字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  171. return NGX_HTTP_PARSE_INVALID_REQUEST;
  172. }
  173. break;
  174. case sw_schema_slash:
  175. // 当前状态为解析<schema>:后紧跟的一个/
  176. switch (ch) {
  177. case '/':
  178. // 如果当前字符正是/
  179. // 置state为sw_schema_slash_slash, 解析紧跟的一个/
  180. state = sw_schema_slash_slash;
  181. break;
  182. default:
  183. // 当前字符不为/, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  184. return NGX_HTTP_PARSE_INVALID_REQUEST;
  185. }
  186. break;
  187. case sw_schema_slash_slash:
  188. // 当前状态为解析<schema>:/后紧跟的一个/
  189. switch (ch) {
  190. case '/':
  191. // 如果当前字符正是/
  192. // 置r->host_start为p-1, 记录URL中主机的起始位置
  193. r->host_start = p - 1;
  194. // 置state为sw_host, 表示解析<schema>://后紧跟的主机
  195. state = sw_host;
  196. break;
  197. default:
  198. // 当前字符不为/, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  199. return NGX_HTTP_PARSE_INVALID_REQUEST;
  200. }
  201. break;
  202. case sw_host:
  203. // 当前状态为解析<schema>://后紧跟的主机
  204. switch (ch) {
  205. case ':':
  206. // 如果当前字符为:, 说明遇到主机后紧跟的一个:了
  207. // 置r->host_end为p-1, 记录主机的结束位置
  208. r->host_end = p - 1;
  209. // 置state为sw_port, 因为遇到主机后紧跟的:了, 那么此:后需要跟着端口号
  210. state = sw_port;
  211. break;
  212. case '/':
  213. // 如果当前字符是/, 因为主机后的:<port>不是必须的,
  214. // 说明遇到主机后紧跟的一个/了
  215. // 置r->host_end为p-1, 记录主机的结束位置
  216. r->host_end = p - 1;
  217. // 置r->uri_start为p-1, 记录URL中路径的起始地址
  218. r->uri_start = p - 1;
  219. // 置state为sw_after_slash_in_uri, 表示解析URL路径中/后的内容
  220. state = sw_after_slash_in_uri;
  221. break;
  222. default:
  223. if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
  224. || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
  225. {
  226. // 如果当前字符为大小写字母、数字、.、-, 说明是主机(域名/IP)的有效字符
  227. // 直接跳过
  228. break;
  229. }
  230. // 当前字符为其他字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  231. return NGX_HTTP_PARSE_INVALID_REQUEST;
  232. }
  233. break;
  234. case sw_port:
  235. // 当前状态为解析<schema>://<host>:后紧跟的端口
  236. switch (ch) {
  237. case '/':
  238. // 如果当前字符为/, 说明遇到端口后紧跟的一个/了
  239. // 置r->port_end为p-1, 记录端口的结束位置
  240. r->port_end = p - 1;
  241. // 置r->uri_start为p-1, 记录URL中路径的起始位置
  242. r->uri_start = p - 1;
  243. // 置state为sw_after_slash_in_uri, 表示解析URL路径中/后的内容
  244. state = sw_after_slash_in_uri;
  245. break;
  246. default:
  247. if (ch < '0' && ch > '9') {
  248. // 如果当前字符不为数字, 端口必须由数字组成, 说明是非法字符
  249. // 返回NGX_HTTP_PARSE_INVALID_REQUEST
  250. return NGX_HTTP_PARSE_INVALID_REQUEST;
  251. }
  252. break;
  253. }
  254. break;
  255. case sw_after_slash_in_uri:
  256. // 当前状态为解析URL路径中/后的内容
  257. switch (ch) {
  258. case CR:
  259. // 如果当前字符为\r, 说明可能是HTTP 0.9
  260. // 置r->uri_end为p-1, 记录URL中路径的结束位置
  261. r->uri_end = p - 1;
  262. // 置r->http_minor为9
  263. r->http_minor = 9;
  264. // 置state为sw_almost_done, 表示解析结束的\n
  265. state = sw_almost_done;
  266. break;
  267. case LF:
  268. // 如果当前字符为\n, 说明可能是HTTP 0.9
  269. // 置r->uri_end为p-1, 记录URL中路径的结束位置
  270. r->uri_end = p - 1;
  271. // 置r->http_minor为9
  272. r->http_minor = 9;
  273. // 置state为sw_done, 表示解析完成
  274. state = sw_done;
  275. break;
  276. case ' ':
  277. // 如果当前字符为空格, 表示遇到URL(或者路径)后紧跟的一个空格
  278. // 置r->uri_end为p-1, 记录URL中路径的结束位置
  279. r->uri_end = p - 1;
  280. // 置state为sw_http_09, 表示解析URL后紧跟空格后的内容
  281. state = sw_http_09;
  282. break;
  283. case '.':
  284. case '%':
  285. // 如果当前字符为.或者%, 说明是复杂的URL
  286. // 置r->complex_uri为1
  287. r->complex_uri = 1;
  288. // 置state为sw_uri
  289. state = sw_uri;
  290. break;
  291. case '/':
  292. // 如果当前字符为/
  293. // 置r->complex_uri为1
  294. // 因为仍要解析/后的内容, 因此state不变
  295. r->complex_uri = 1;
  296. break;
  297. case '?':
  298. // 如果当前字符为?, 说明遇到了URL中的参数
  299. // 置r->args_start为p, 记录参数的起始位置
  300. r->args_start = p;
  301. // 置state为sw_uri
  302. state = sw_uri;
  303. break;
  304. default:
  305. // 如果当前字符为其他字符
  306. // 置state为sw_check_uri
  307. state = sw_check_uri;
  308. break;
  309. }
  310. break;
  311. case sw_check_uri:
  312. // 当前状态为sw_check_uri
  313. switch (ch) {
  314. case CR:
  315. // 如果当前字符为\r, 说明遇到了URL后紧跟的\r
  316. // 置r->uri_end为p-1, 记录URL的结束位置
  317. r->uri_end = p - 1;
  318. // 显然是HTTP 0.9, 置r->http_minor为9
  319. r->http_minor = 9;
  320. // 置state为sw_almost_done, 表示解析结束的\n
  321. state = sw_almost_done;
  322. break;
  323. case LF:
  324. // 如果当前字符为\n, 说明遇到了URL后紧跟的\n
  325. // 置r->uri_end为p-1, 记录URL的结束位置
  326. r->uri_end = p - 1;
  327. // 显然是HTTP 0.9, 置r->http_minor为9
  328. r->http_minor = 9;
  329. // 置state为sw_done, 表示解析完成
  330. state = sw_done;
  331. break;
  332. case ' ':
  333. // 如果当前字符为空格, 表明遇到URL后紧跟的一个空格
  334. // 置r->uri_end为p-1, 记录URL的结束位置
  335. r->uri_end = p - 1;
  336. // 置state为sw_http_09, 表示解析URL后紧跟空格后的内容
  337. state = sw_http_09;
  338. break;
  339. case '.':
  340. // 如果当前字符为., 表明遇到扩展名
  341. // 置r->uri_ext为p, 记录扩展名的起始位置
  342. r->uri_ext = p;
  343. break;
  344. case '/':
  345. // 如果当前字符为/
  346. // 那么之前记录的"扩展名"其实不是真的扩展名, 置r->uri_ext为空
  347. r->uri_ext = NULL;
  348. // 置state为sw_after_slash_in_uri, 因为仍在解析URL且遇到了/
  349. state = sw_after_slash_in_uri;
  350. break;
  351. case '%':
  352. // 如果当前字符为%, 表明是复杂的URL
  353. // 置r->complex_uri为1
  354. r->complex_uri = 1;
  355. // 置state为sw_uri
  356. state = sw_uri;
  357. break;
  358. case '?':
  359. // 如果当前字符为?, 表明遇到了参数
  360. // 置r->args_start为p, 记录参数的起始位置
  361. r->args_start = p;
  362. // 置state为sw_uri
  363. state = sw_uri;
  364. break;
  365. }
  366. break;
  367. case sw_uri:
  368. // 当前状态为sw_uri
  369. switch (ch) {
  370. case CR:
  371. // 如果当前字符为\r, 说明遇到了URL后紧跟的\r
  372. // 置r->uri_end为p-1, 记录URL的结束位置
  373. r->uri_end = p - 1;
  374. // 显然是HTTP 0.9, 置r->http_minor为9
  375. r->http_minor = 9;
  376. // 置state为sw_almost_done, 表示解析结束的\n
  377. state = sw_almost_done;
  378. break;
  379. case LF:
  380. // 如果当前字符为\n, 说明遇到了URL后紧跟的\n
  381. // 置r->uri_end为p-1, 记录URL的结束位置
  382. r->uri_end = p - 1;
  383. // 显然是HTTP 0.9, 置r->http_minor为9
  384. r->http_minor = 9;
  385. // 置state为sw_done, 表示解析完成
  386. state = sw_done;
  387. break;
  388. case ' ':
  389. // 如果当前字符为空格, 表明遇到URL后紧跟的一个空格
  390. // 置r->uri_end为p-1, 记录URL的结束位置
  391. r->uri_end = p - 1;
  392. // 置state为sw_http_09, 表示解析URL后紧跟空格后的内容
  393. state = sw_http_09;
  394. break;
  395. }
  396. break;
  397. case sw_http_09:
  398. // 当前状态为解析URL后紧跟空格后的内容
  399. switch (ch) {
  400. case ' ':
  401. // 如果当前字符为空格, 直接跳过
  402. break;
  403. case CR:
  404. // 如果当前字符为\r, 说明是HTTP 0.9
  405. // 置r->http_minor为9
  406. r->http_minor = 9;
  407. // 置state为sw_almost_done, 表示解析结束的\n
  408. state = sw_almost_done;
  409. break;
  410. case LF:
  411. // 如果当前字符为\n, 说明是HTTP 0.9
  412. // 置r->http_minor为9
  413. r->http_minor = 9;
  414. // 置state为sw_done, 表示解析完成
  415. state = sw_done;
  416. break;
  417. case 'H':
  418. // 如果当前字符是H, 说明是HTTP >= 1.0
  419. // 置state为sw_http_H, 表示解析协议版本的第二个字符T
  420. state = sw_http_H;
  421. break;
  422. default:
  423. // 当前字符为其他字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  424. return NGX_HTTP_PARSE_INVALID_REQUEST;
  425. }
  426. break;
  427. case sw_http_H:
  428. // 当前状态为解析协议版本的第二个字符T
  429. switch (ch) {
  430. case 'T':
  431. // 如果当前字符正是T
  432. // 置state为sw_http_HT
  433. state = sw_http_HT;
  434. break;
  435. default:
  436. // 当前字符不为T, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  437. return NGX_HTTP_PARSE_INVALID_REQUEST;
  438. }
  439. break;
  440. case sw_http_HT:
  441. // 当前状态为解析协议版本的第三个字符T
  442. switch (ch) {
  443. case 'T':
  444. // 如果当前字符正是T
  445. // 置state为sw_http_HTT
  446. state = sw_http_HTT;
  447. break;
  448. default:
  449. // 当前字符不为T, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  450. return NGX_HTTP_PARSE_INVALID_REQUEST;
  451. }
  452. break;
  453. case sw_http_HTT:
  454. // 当前状态为解析协议版本的第四个字符P
  455. switch (ch) {
  456. case 'P':
  457. // 如果当前字符正是P
  458. // 置state为sw_http_HTTP
  459. state = sw_http_HTTP;
  460. break;
  461. default:
  462. // 当前字符不为P, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  463. return NGX_HTTP_PARSE_INVALID_REQUEST;
  464. }
  465. break;
  466. case sw_http_HTTP:
  467. // 当前状态为解析协议版本的第五个字符/
  468. switch (ch) {
  469. case '/':
  470. // 如果当前字符正是/
  471. // 置state为sw_first_major_digit
  472. state = sw_first_major_digit;
  473. break;
  474. default:
  475. // 当前字符不为/, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  476. return NGX_HTTP_PARSE_INVALID_REQUEST;
  477. }
  478. break;
  479. case sw_first_major_digit:
  480. // 当前状态为解析协议版本的主版本号的第一个数字
  481. if (ch < '1' || ch > '9') {
  482. // 如果当前字符不为数字1-9, 说明是无效字符;
  483. // 协议版本应该是在HTTP 1.0后才有的, 因此主版本号应该不小于1;
  484. // 返回NGX_HTTP_PARSE_INVALID_REQUEST
  485. return NGX_HTTP_PARSE_INVALID_REQUEST;
  486. }
  487. // 置r->http_major为ch-'0', 记录主版本号
  488. r->http_major = ch - '0';
  489. // 置state为sw_major_digit, 表示解析协议版本的主版本号第一个数字后的数字或者.
  490. state = sw_major_digit;
  491. break;
  492. case sw_major_digit:
  493. // 当前状态为解析协议版本的主版本号第一个数字后的数字或者.
  494. if (ch == '.') {
  495. // 如果当前字符为., 说明遇到主版本号后紧跟的.了
  496. // 置state为sw_first_minor_digit, 表示解析次版本号的第一个数字
  497. state = sw_first_minor_digit;
  498. break;
  499. }
  500. if (ch < '0' || ch > '9') {
  501. // 如果当前字符不为数字, 说明是非法字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  502. return NGX_HTTP_PARSE_INVALID_REQUEST;
  503. }
  504. // 更新主版本号r->http_major
  505. r->http_major = r->http_major * 10 + ch - '0';
  506. break;
  507. case sw_first_minor_digit:
  508. // 当前状态为解析协议版本的次版本号的第一个数字
  509. if (ch < '0' || ch > '9') {
  510. // 如果当前字符不为数字, 说明是非法字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  511. return NGX_HTTP_PARSE_INVALID_REQUEST;
  512. }
  513. // 置r->http_minor为ch-'0', 记录次版本号
  514. r->http_minor = ch - '0';
  515. // 置state为sw_minor_digit, 表示解析协议版本的次版本号第一个数字后的数字
  516. state = sw_minor_digit;
  517. break;
  518. case sw_minor_digit:
  519. // 当前状态为解析协议版本的次版本号第一个数字后的数字
  520. if (ch == CR) {
  521. // 如果当前字符为\r, 说明遇到次版本号后紧跟的\r
  522. // 置state为sw_almost_done, 表示解析结束的\n
  523. state = sw_almost_done;
  524. break;
  525. }
  526. if (ch == LF) {
  527. // 如果当前字符为\n, 说明遇到次版本号后的\n
  528. // 置state为sw_done, 表示解析完成
  529. state = sw_done;
  530. break;
  531. }
  532. if (ch < '0' || ch > '9') {
  533. // 如果当前字符不为数字, 说明是非法字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  534. return NGX_HTTP_PARSE_INVALID_REQUEST;
  535. }
  536. // 更新次版本号r->http_minor
  537. r->http_minor = r->http_minor * 10 + ch - '0';
  538. break;
  539. case sw_almost_done:
  540. // 当前状态为解析结束的\n
  541. // 置r->request_end为p-2, 记录请求行有效内容的结束位置
  542. r->request_end = p - 2;
  543. switch (ch) {
  544. case LF:
  545. // 如果当前字符正是\n
  546. // 置state为sw_done, 表示解析完成
  547. state = sw_done;
  548. break;
  549. default:
  550. // 如果当前字符不是\n, 那么就是非法字符, 返回NGX_HTTP_PARSE_INVALID_REQUEST
  551. return NGX_HTTP_PARSE_INVALID_REQUEST;
  552. }
  553. break;
  554. case sw_done:
  555. // 当前状态为解析完成, 直接退出循环
  556. break;
  557. }
  558. }
  559. // 置缓冲区的pos为p
  560. b->pos = p;
  561. if (state == sw_done) {
  562. // 如果state为sw_done, 表明解析完成
  563. if (r->request_end == NULL) {
  564. // 如果r->request_end为空
  565. // 置r->request_end为p-1, p-1即为请求行的结束位置
  566. r->request_end = p - 1;
  567. }
  568. // 求取HTTP版本, 规则为: 主版本号*1000+次版本号
  569. // 所以,0.9->9, 1.0->1000, 1.1->1001
  570. r->http_version = r->http_major * 1000 + r->http_minor;
  571. // 重置请求r的state为sw_start
  572. r->state = sw_start;
  573. if (r->http_version == 9 && r->method != NGX_HTTP_GET) {
  574. // 如果为HTTP 0.9且请求方法不为GET
  575. // 返回NGX_HTTP_PARSE_INVALID_09_METHOD, 说明HTTP 0.9只支持GET方法
  576. return NGX_HTTP_PARSE_INVALID_09_METHOD;
  577. }
  578. return NGX_OK;
  579. } else {
  580. // 没有解析完
  581. // 记录当前解析状态
  582. r->state = state;
  583. // 返回NGX_AGAIN
  584. return NGX_AGAIN;
  585. }
  586. }

-——————————
作者:疯之墒
来源:CSDN
原文:https://blog.csdn.net/oyw5201314ck/article/details/78550785
版权声明:本文为博主原创文章,转载请附上博文链接!

发表评论

表情:
评论列表 (有 0 条评论,245人围观)

还没有评论,来说两句吧...

相关阅读

    相关 HTTP头部请求参数

    HTTP响应头和请求头信息对照表 HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。HTTP的头信息包括通用头、请求头、响应头和实体头四个部分。每个头域由一个域