Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/modules/proxy/ngx_http_proxy_parse.c')
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_parse.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/http/modules/proxy/ngx_http_proxy_parse.c b/src/http/modules/proxy/ngx_http_proxy_parse.c
new file mode 100644
index 000000000..85c406ea7
--- /dev/null
+++ b/src/http/modules/proxy/ngx_http_proxy_parse.c
@@ -0,0 +1,204 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include <ngx_http_proxy_handler.h>
+
+
+int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
+{
+ char ch;
+ char *pos;
+ 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,
+ sw_done
+ } state;
+
+ state = p->state;
+ pos = p->header_in->pos;
+
+ while (pos < p->header_in->last && state < sw_done) {
+ ch = *pos++;
+
+ switch (state) {
+
+ /* "HTTP/" */
+ case sw_start:
+ switch (ch) {
+ case 'H':
+ state = sw_H;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_H:
+ switch (ch) {
+ case 'T':
+ state = sw_HT;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HT:
+ switch (ch) {
+ case 'T':
+ state = sw_HTT;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HTT:
+ switch (ch) {
+ case 'P':
+ state = sw_HTTP;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HTTP:
+ switch (ch) {
+ case '/':
+ state = sw_first_major_digit;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ /* the first digit of major HTTP version */
+ case sw_first_major_digit:
+ if (ch < '1' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ 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_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ break;
+
+ /* the first digit of minor HTTP version */
+ case sw_first_minor_digit:
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ 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_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ break;
+
+ /* HTTP status code */
+ case sw_status:
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ p->status = p->status * 10 + ch - '0';
+
+ if (++p->status_count == 3) {
+ state = sw_space_after_status;
+ p->status_start = pos - 3;
+ }
+
+ break;
+
+ /* space or end of line */
+ case sw_space_after_status:
+ switch (ch) {
+ case ' ':
+ state = sw_status_text;
+ break;
+ case CR:
+ state = sw_almost_done;
+ break;
+ case LF:
+ state = sw_done;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ /* any text until end of line */
+ case sw_status_text:
+ switch (ch) {
+ case CR:
+ state = sw_almost_done;
+
+ break;
+ case LF:
+ state = sw_done;
+ break;
+ }
+ break;
+
+ /* end of request line */
+ case sw_almost_done:
+ p->status_end = pos - 2;
+ switch (ch) {
+ case LF:
+ state = sw_done;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+ }
+ }
+
+ p->header_in->pos = pos;
+
+ if (state == sw_done) {
+ if (p->status_end == NULL) {
+ p->status_end = pos - 1;
+ }
+
+ p->state = sw_start;
+ return NGX_OK;
+ }
+
+ p->state = state;
+ return NGX_AGAIN;
+}