Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_uwsgi_module.c @ 580:4d3e880ce86c NGINX_0_8_42
nginx 0.8.42
*) Change: now nginx tests locations given by regular expressions, if
request was matched exactly by a location given by a prefix string.
The previous behavior has been introduced in 0.7.1.
*) Feature: the ngx_http_scgi_module.
Thanks to Manlio Perillo.
*) Feature: a text answer may be added to a "return" directive.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 21 Jun 2010 00:00:00 +0400 |
parents | bc110f60c0de |
children | 016632f0fb18 |
comparison
equal
deleted
inserted
replaced
579:c570633043e7 | 580:4d3e880ce86c |
---|---|
34 ngx_uint_t modifier1; | 34 ngx_uint_t modifier1; |
35 ngx_uint_t modifier2; | 35 ngx_uint_t modifier2; |
36 } ngx_http_uwsgi_loc_conf_t; | 36 } ngx_http_uwsgi_loc_conf_t; |
37 | 37 |
38 | 38 |
39 typedef struct { | |
40 ngx_uint_t status; | |
41 ngx_uint_t status_count; | |
42 u_char *status_start; | |
43 u_char *status_end; | |
44 } ngx_http_uwsgi_ctx_t; | |
45 | |
46 | |
47 #define NGX_HTTP_UWSGI_PARSE_NO_HEADER 20 | |
48 | |
49 | |
50 static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r, | 39 static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r, |
51 ngx_http_uwsgi_loc_conf_t *uwcf); | 40 ngx_http_uwsgi_loc_conf_t *uwcf); |
52 static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r); | 41 static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r); |
53 static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r); | 42 static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r); |
54 static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r); | 43 static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r); |
55 static ngx_int_t ngx_http_uwsgi_parse_status_line(ngx_http_request_t *r, | |
56 ngx_http_uwsgi_ctx_t *ctx); | |
57 static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); | 44 static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); |
58 static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); | 45 static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); |
59 static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r); | 46 static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r); |
60 static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, | 47 static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, |
61 ngx_int_t rc); | 48 ngx_int_t rc); |
424 | 411 |
425 static ngx_int_t | 412 static ngx_int_t |
426 ngx_http_uwsgi_handler(ngx_http_request_t *r) | 413 ngx_http_uwsgi_handler(ngx_http_request_t *r) |
427 { | 414 { |
428 ngx_int_t rc; | 415 ngx_int_t rc; |
416 ngx_http_status_t *status; | |
429 ngx_http_upstream_t *u; | 417 ngx_http_upstream_t *u; |
430 ngx_http_uwsgi_ctx_t *ctx; | |
431 ngx_http_uwsgi_loc_conf_t *uwcf; | 418 ngx_http_uwsgi_loc_conf_t *uwcf; |
432 | 419 |
433 if (r->subrequest_in_memory) { | 420 if (r->subrequest_in_memory) { |
434 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 421 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
435 "ngx_http_uwsgi_module does not support " | 422 "ngx_http_uwsgi_module does not support " |
439 | 426 |
440 if (ngx_http_upstream_create(r) != NGX_OK) { | 427 if (ngx_http_upstream_create(r) != NGX_OK) { |
441 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 428 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
442 } | 429 } |
443 | 430 |
444 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_uwsgi_ctx_t)); | 431 status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t)); |
445 if (ctx == NULL) { | 432 if (status == NULL) { |
446 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 433 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
447 } | 434 } |
448 | 435 |
449 ngx_http_set_ctx(r, ctx, ngx_http_uwsgi_module); | 436 ngx_http_set_ctx(r, status, ngx_http_uwsgi_module); |
450 | 437 |
451 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); | 438 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); |
452 | 439 |
453 if (uwcf->uwsgi_lengths) { | 440 if (uwcf->uwsgi_lengths) { |
454 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) { | 441 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) { |
844 | 831 |
845 | 832 |
846 static ngx_int_t | 833 static ngx_int_t |
847 ngx_http_uwsgi_reinit_request(ngx_http_request_t *r) | 834 ngx_http_uwsgi_reinit_request(ngx_http_request_t *r) |
848 { | 835 { |
849 ngx_http_uwsgi_ctx_t *ctx; | 836 ngx_http_status_t *status; |
850 | 837 |
851 ctx = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module); | 838 status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module); |
852 | 839 |
853 if (ctx == NULL) { | 840 if (status == NULL) { |
854 return NGX_OK; | 841 return NGX_OK; |
855 } | 842 } |
856 | 843 |
857 ctx->status = 0; | 844 status->code = 0; |
858 ctx->status_count = 0; | 845 status->count = 0; |
859 ctx->status_start = NULL; | 846 status->start = NULL; |
860 ctx->status_end = NULL; | 847 status->end = NULL; |
861 | 848 |
862 r->upstream->process_header = ngx_http_uwsgi_process_status_line; | 849 r->upstream->process_header = ngx_http_uwsgi_process_status_line; |
863 | |
864 return NGX_OK; | |
865 } | |
866 | |
867 static ngx_int_t | |
868 ngx_http_uwsgi_parse_status_line(ngx_http_request_t *r, | |
869 ngx_http_uwsgi_ctx_t *ctx) | |
870 { | |
871 u_char ch; | |
872 u_char *p; | |
873 ngx_http_upstream_t *u; | |
874 enum { | |
875 sw_start = 0, | |
876 sw_H, | |
877 sw_HT, | |
878 sw_HTT, | |
879 sw_HTTP, | |
880 sw_first_major_digit, | |
881 sw_major_digit, | |
882 sw_first_minor_digit, | |
883 sw_minor_digit, | |
884 sw_status, | |
885 sw_space_after_status, | |
886 sw_status_text, | |
887 sw_almost_done | |
888 } state; | |
889 | |
890 u = r->upstream; | |
891 | |
892 state = r->state; | |
893 | |
894 for (p = u->buffer.pos; p < u->buffer.last; p++) { | |
895 ch = *p; | |
896 | |
897 switch (state) { | |
898 | |
899 /* "HTTP/" */ | |
900 case sw_start: | |
901 switch (ch) { | |
902 case 'H': | |
903 state = sw_H; | |
904 break; | |
905 default: | |
906 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
907 } | |
908 break; | |
909 | |
910 case sw_H: | |
911 switch (ch) { | |
912 case 'T': | |
913 state = sw_HT; | |
914 break; | |
915 default: | |
916 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
917 } | |
918 break; | |
919 | |
920 case sw_HT: | |
921 switch (ch) { | |
922 case 'T': | |
923 state = sw_HTT; | |
924 break; | |
925 default: | |
926 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
927 } | |
928 break; | |
929 | |
930 case sw_HTT: | |
931 switch (ch) { | |
932 case 'P': | |
933 state = sw_HTTP; | |
934 break; | |
935 default: | |
936 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
937 } | |
938 break; | |
939 | |
940 case sw_HTTP: | |
941 switch (ch) { | |
942 case '/': | |
943 state = sw_first_major_digit; | |
944 break; | |
945 default: | |
946 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
947 } | |
948 break; | |
949 | |
950 /* the first digit of major HTTP version */ | |
951 case sw_first_major_digit: | |
952 if (ch < '1' || ch > '9') { | |
953 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
954 } | |
955 | |
956 state = sw_major_digit; | |
957 break; | |
958 | |
959 /* the major HTTP version or dot */ | |
960 case sw_major_digit: | |
961 if (ch == '.') { | |
962 state = sw_first_minor_digit; | |
963 break; | |
964 } | |
965 | |
966 if (ch < '0' || ch > '9') { | |
967 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
968 } | |
969 | |
970 break; | |
971 | |
972 /* the first digit of minor HTTP version */ | |
973 case sw_first_minor_digit: | |
974 if (ch < '0' || ch > '9') { | |
975 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
976 } | |
977 | |
978 state = sw_minor_digit; | |
979 break; | |
980 | |
981 /* the minor HTTP version or the end of the request line */ | |
982 case sw_minor_digit: | |
983 if (ch == ' ') { | |
984 state = sw_status; | |
985 break; | |
986 } | |
987 | |
988 if (ch < '0' || ch > '9') { | |
989 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
990 } | |
991 | |
992 break; | |
993 | |
994 /* HTTP status code */ | |
995 case sw_status: | |
996 if (ch == ' ') { | |
997 break; | |
998 } | |
999 | |
1000 if (ch < '0' || ch > '9') { | |
1001 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
1002 } | |
1003 | |
1004 ctx->status = ctx->status * 10 + ch - '0'; | |
1005 | |
1006 if (++ctx->status_count == 3) { | |
1007 state = sw_space_after_status; | |
1008 ctx->status_start = p - 2; | |
1009 } | |
1010 | |
1011 break; | |
1012 | |
1013 /* space or end of line */ | |
1014 case sw_space_after_status: | |
1015 switch (ch) { | |
1016 case ' ': | |
1017 state = sw_status_text; | |
1018 break; | |
1019 case '.': /* IIS may send 403.1, 403.2, etc */ | |
1020 state = sw_status_text; | |
1021 break; | |
1022 case CR: | |
1023 state = sw_almost_done; | |
1024 break; | |
1025 case LF: | |
1026 goto done; | |
1027 default: | |
1028 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
1029 } | |
1030 break; | |
1031 | |
1032 /* any text until end of line */ | |
1033 case sw_status_text: | |
1034 switch (ch) { | |
1035 case CR: | |
1036 state = sw_almost_done; | |
1037 | |
1038 break; | |
1039 case LF: | |
1040 goto done; | |
1041 } | |
1042 break; | |
1043 | |
1044 /* end of status line */ | |
1045 case sw_almost_done: | |
1046 ctx->status_end = p - 1; | |
1047 switch (ch) { | |
1048 case LF: | |
1049 goto done; | |
1050 default: | |
1051 return NGX_HTTP_UWSGI_PARSE_NO_HEADER; | |
1052 } | |
1053 } | |
1054 } | |
1055 | |
1056 u->buffer.pos = p; | |
1057 r->state = state; | |
1058 | |
1059 return NGX_AGAIN; | |
1060 | |
1061 done: | |
1062 | |
1063 u->buffer.pos = p + 1; | |
1064 | |
1065 if (ctx->status_end == NULL) { | |
1066 ctx->status_end = p; | |
1067 } | |
1068 | |
1069 r->state = sw_start; | |
1070 | 850 |
1071 return NGX_OK; | 851 return NGX_OK; |
1072 } | 852 } |
1073 | 853 |
1074 | 854 |
1075 static ngx_int_t | 855 static ngx_int_t |
1076 ngx_http_uwsgi_process_status_line(ngx_http_request_t *r) | 856 ngx_http_uwsgi_process_status_line(ngx_http_request_t *r) |
1077 { | 857 { |
1078 ngx_int_t rc; | 858 size_t len; |
859 ngx_int_t rc; | |
860 ngx_http_status_t *status; | |
1079 ngx_http_upstream_t *u; | 861 ngx_http_upstream_t *u; |
1080 ngx_http_uwsgi_ctx_t *ctx; | 862 |
1081 | 863 status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module); |
1082 ctx = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module); | 864 |
1083 | 865 if (status == NULL) { |
1084 if (ctx == NULL) { | |
1085 return NGX_ERROR; | 866 return NGX_ERROR; |
1086 } | 867 } |
1087 | 868 |
1088 rc = ngx_http_uwsgi_parse_status_line(r, ctx); | 869 u = r->upstream; |
870 | |
871 rc = ngx_http_parse_status_line(r, &u->buffer, status); | |
1089 | 872 |
1090 if (rc == NGX_AGAIN) { | 873 if (rc == NGX_AGAIN) { |
1091 return rc; | 874 return rc; |
1092 } | 875 } |
1093 | 876 |
1094 u = r->upstream; | 877 if (rc == NGX_ERROR) { |
1095 | |
1096 if (rc == NGX_HTTP_UWSGI_PARSE_NO_HEADER) { | |
1097 | |
1098 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1099 "upstream sent no valid HTTP/1.0 header"); | |
1100 | |
1101 r->http_version = NGX_HTTP_VERSION_9; | 878 r->http_version = NGX_HTTP_VERSION_9; |
1102 u->headers_in.status_n = NGX_HTTP_OK; | 879 |
1103 u->state->status = NGX_HTTP_OK; | 880 u->process_header = ngx_http_uwsgi_process_header; |
1104 | 881 |
1105 return NGX_OK; | 882 return ngx_http_uwsgi_process_header(r); |
1106 } | 883 } |
1107 | 884 |
1108 if (u->state) { | 885 if (u->state) { |
1109 u->state->status = ctx->status; | 886 u->state->status = status->code; |
1110 } | 887 } |
1111 | 888 |
1112 u->headers_in.status_n = ctx->status; | 889 u->headers_in.status_n = status->code; |
1113 | 890 |
1114 u->headers_in.status_line.len = ctx->status_end - ctx->status_start; | 891 len = status->end - status->start; |
1115 u->headers_in.status_line.data = ngx_pnalloc(r->pool, | 892 u->headers_in.status_line.len = len; |
1116 u->headers_in.status_line.len); | 893 |
894 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); | |
1117 if (u->headers_in.status_line.data == NULL) { | 895 if (u->headers_in.status_line.data == NULL) { |
1118 return NGX_ERROR; | 896 return NGX_ERROR; |
1119 } | 897 } |
1120 | 898 |
1121 ngx_memcpy(u->headers_in.status_line.data, ctx->status_start, | 899 ngx_memcpy(u->headers_in.status_line.data, status->start, len); |
1122 u->headers_in.status_line.len); | |
1123 | 900 |
1124 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 901 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1125 "http uwsgi status %ui \"%V\"", | 902 "http uwsgi status %ui \"%V\"", |
1126 u->headers_in.status_n, &u->headers_in.status_line); | 903 u->headers_in.status_n, &u->headers_in.status_line); |
1127 | 904 |
1132 | 909 |
1133 | 910 |
1134 static ngx_int_t | 911 static ngx_int_t |
1135 ngx_http_uwsgi_process_header(ngx_http_request_t *r) | 912 ngx_http_uwsgi_process_header(ngx_http_request_t *r) |
1136 { | 913 { |
1137 ngx_int_t rc; | 914 ngx_str_t *status_line; |
915 ngx_int_t rc, status; | |
1138 ngx_table_elt_t *h; | 916 ngx_table_elt_t *h; |
917 ngx_http_upstream_t *u; | |
1139 ngx_http_upstream_header_t *hh; | 918 ngx_http_upstream_header_t *hh; |
1140 ngx_http_upstream_main_conf_t *umcf; | 919 ngx_http_upstream_main_conf_t *umcf; |
1141 | 920 |
1142 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | 921 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
1143 | 922 |
1196 | 975 |
1197 /* a whole header has been parsed successfully */ | 976 /* a whole header has been parsed successfully */ |
1198 | 977 |
1199 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 978 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1200 "http uwsgi header done"); | 979 "http uwsgi header done"); |
980 | |
981 if (r->http_version > NGX_HTTP_VERSION_9) { | |
982 return NGX_OK; | |
983 } | |
984 | |
985 u = r->upstream; | |
986 | |
987 if (u->headers_in.status) { | |
988 status_line = &u->headers_in.status->value; | |
989 | |
990 status = ngx_atoi(status_line->data, 3); | |
991 if (status == NGX_ERROR) { | |
992 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
993 "upstream sent invalid status \"%V\"", | |
994 status_line); | |
995 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
996 } | |
997 | |
998 r->http_version = NGX_HTTP_VERSION_10; | |
999 u->headers_in.status_n = status; | |
1000 u->headers_in.status_line = *status_line; | |
1001 | |
1002 } else if (u->headers_in.location) { | |
1003 r->http_version = NGX_HTTP_VERSION_10; | |
1004 u->headers_in.status_n = 302; | |
1005 ngx_str_set(&u->headers_in.status_line, | |
1006 "302 Moved Temporarily"); | |
1007 | |
1008 } else { | |
1009 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1010 "upstream sent neither valid HTTP/1.0 header " | |
1011 "nor \"Status\" header line"); | |
1012 u->headers_in.status_n = 200; | |
1013 ngx_str_set(&u->headers_in.status_line, "200 OK"); | |
1014 } | |
1015 | |
1016 if (u->state) { | |
1017 u->state->status = u->headers_in.status_n; | |
1018 } | |
1201 | 1019 |
1202 return NGX_OK; | 1020 return NGX_OK; |
1203 } | 1021 } |
1204 | 1022 |
1205 if (rc == NGX_AGAIN) { | 1023 if (rc == NGX_AGAIN) { |