ngx_http_parse_status_line()
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index bb19daf..9351cb0 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -51,6 +51,14 @@
};
+typedef struct {
+ ngx_uint_t code;
+ ngx_uint_t count;
+ u_char *start;
+ u_char *end;
+} ngx_http_status_t;
+
+
#define ngx_http_get_module_ctx(r, module) (r)->ctx[module.ctx_index]
#define ngx_http_set_ctx(r, c, module) r->ctx[module.ctx_index] = c;
@@ -70,6 +78,8 @@
ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b);
ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r,
ngx_uint_t merge_slashes);
+ngx_int_t ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
+ ngx_http_status_t *status);
ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
ngx_str_t *args, ngx_uint_t *flags);
ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 6facc82..f5be2f0 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -1318,6 +1318,211 @@
ngx_int_t
+ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
+ ngx_http_status_t *status)
+{
+ u_char ch;
+ u_char *p;
+ enum {
+ sw_start = 0,
+ sw_H,
+ sw_HT,
+ sw_HTT,
+ sw_HTTP,
+ sw_first_major_digit,
+ sw_major_digit,
+ sw_first_minor_digit,
+ sw_minor_digit,
+ sw_status,
+ sw_space_after_status,
+ sw_status_text,
+ sw_almost_done
+ } state;
+
+ state = r->state;
+
+ for (p = b->pos; p < b->last; p++) {
+ ch = *p;
+
+ switch (state) {
+
+ /* "HTTP/" */
+ case sw_start:
+ switch (ch) {
+ case 'H':
+ state = sw_H;
+ break;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ case sw_H:
+ switch (ch) {
+ case 'T':
+ state = sw_HT;
+ break;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ case sw_HT:
+ switch (ch) {
+ case 'T':
+ state = sw_HTT;
+ break;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ case sw_HTT:
+ switch (ch) {
+ case 'P':
+ state = sw_HTTP;
+ break;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ case sw_HTTP:
+ switch (ch) {
+ case '/':
+ state = sw_first_major_digit;
+ break;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ /* the first digit of major HTTP version */
+ case sw_first_major_digit:
+ if (ch < '1' || ch > '9') {
+ return NGX_ERROR;
+ }
+
+ state = sw_major_digit;
+ break;
+
+ /* the major HTTP version or dot */
+ case sw_major_digit:
+ if (ch == '.') {
+ state = sw_first_minor_digit;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') {
+ return NGX_ERROR;
+ }
+
+ break;
+
+ /* the first digit of minor HTTP version */
+ case sw_first_minor_digit:
+ if (ch < '0' || ch > '9') {
+ return NGX_ERROR;
+ }
+
+ state = sw_minor_digit;
+ break;
+
+ /* the minor HTTP version or the end of the request line */
+ case sw_minor_digit:
+ if (ch == ' ') {
+ state = sw_status;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') {
+ return NGX_ERROR;
+ }
+
+ break;
+
+ /* HTTP status code */
+ case sw_status:
+ if (ch == ' ') {
+ break;
+ }
+
+ if (ch < '0' || ch > '9') {
+ return NGX_ERROR;
+ }
+
+ status->code = status->code * 10 + ch - '0';
+
+ if (++status->count == 3) {
+ state = sw_space_after_status;
+ status->start = p - 2;
+ }
+
+ break;
+
+ /* space or end of line */
+ case sw_space_after_status:
+ switch (ch) {
+ case ' ':
+ state = sw_status_text;
+ break;
+ case '.': /* IIS may send 403.1, 403.2, etc */
+ state = sw_status_text;
+ break;
+ case CR:
+ state = sw_almost_done;
+ break;
+ case LF:
+ goto done;
+ default:
+ return NGX_ERROR;
+ }
+ break;
+
+ /* any text until end of line */
+ case sw_status_text:
+ switch (ch) {
+ case CR:
+ state = sw_almost_done;
+
+ break;
+ case LF:
+ goto done;
+ }
+ break;
+
+ /* end of status line */
+ case sw_almost_done:
+ status->end = p - 1;
+ switch (ch) {
+ case LF:
+ goto done;
+ default:
+ return NGX_ERROR;
+ }
+ }
+ }
+
+ b->pos = p;
+ r->state = state;
+
+ return NGX_AGAIN;
+
+done:
+
+ b->pos = p + 1;
+
+ if (status->end == NULL) {
+ status->end = p;
+ }
+
+ r->state = sw_start;
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
ngx_str_t *args, ngx_uint_t *flags)
{