Mercurial > hg > nginx-vendor-1-0
comparison src/http/modules/ngx_http_proxy_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 |
---|---|
75 ngx_uint_t headers_hash_bucket_size; | 75 ngx_uint_t headers_hash_bucket_size; |
76 } ngx_http_proxy_loc_conf_t; | 76 } ngx_http_proxy_loc_conf_t; |
77 | 77 |
78 | 78 |
79 typedef struct { | 79 typedef struct { |
80 ngx_uint_t status; | 80 ngx_http_status_t status; |
81 ngx_uint_t status_count; | |
82 u_char *status_start; | |
83 u_char *status_end; | |
84 | |
85 ngx_http_proxy_vars_t vars; | 81 ngx_http_proxy_vars_t vars; |
86 | |
87 size_t internal_body_length; | 82 size_t internal_body_length; |
88 } ngx_http_proxy_ctx_t; | 83 } ngx_http_proxy_ctx_t; |
89 | |
90 | |
91 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 | |
92 | 84 |
93 | 85 |
94 static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r, | 86 static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r, |
95 ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf); | 87 ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf); |
96 #if (NGX_HTTP_CACHE) | 88 #if (NGX_HTTP_CACHE) |
97 static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r); | 89 static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r); |
98 #endif | 90 #endif |
99 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); | 91 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); |
100 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); | 92 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); |
101 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r); | 93 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r); |
102 static ngx_int_t ngx_http_proxy_parse_status_line(ngx_http_request_t *r, | |
103 ngx_http_proxy_ctx_t *ctx); | |
104 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); | 94 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); |
105 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); | 95 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); |
106 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, | 96 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, |
107 ngx_int_t rc); | 97 ngx_int_t rc); |
108 | 98 |
1178 | 1168 |
1179 if (ctx == NULL) { | 1169 if (ctx == NULL) { |
1180 return NGX_OK; | 1170 return NGX_OK; |
1181 } | 1171 } |
1182 | 1172 |
1183 ctx->status = 0; | 1173 ctx->status.code = 0; |
1184 ctx->status_count = 0; | 1174 ctx->status.count = 0; |
1185 ctx->status_start = NULL; | 1175 ctx->status.start = NULL; |
1186 ctx->status_end = NULL; | 1176 ctx->status.end = NULL; |
1187 | 1177 |
1188 r->upstream->process_header = ngx_http_proxy_process_status_line; | 1178 r->upstream->process_header = ngx_http_proxy_process_status_line; |
1189 r->state = 0; | 1179 r->state = 0; |
1190 | 1180 |
1191 return NGX_OK; | 1181 return NGX_OK; |
1193 | 1183 |
1194 | 1184 |
1195 static ngx_int_t | 1185 static ngx_int_t |
1196 ngx_http_proxy_process_status_line(ngx_http_request_t *r) | 1186 ngx_http_proxy_process_status_line(ngx_http_request_t *r) |
1197 { | 1187 { |
1188 size_t len; | |
1198 ngx_int_t rc; | 1189 ngx_int_t rc; |
1199 ngx_http_upstream_t *u; | 1190 ngx_http_upstream_t *u; |
1200 ngx_http_proxy_ctx_t *ctx; | 1191 ngx_http_proxy_ctx_t *ctx; |
1201 | 1192 |
1202 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | 1193 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1203 | 1194 |
1204 if (ctx == NULL) { | 1195 if (ctx == NULL) { |
1205 return NGX_ERROR; | 1196 return NGX_ERROR; |
1206 } | 1197 } |
1207 | 1198 |
1208 rc = ngx_http_proxy_parse_status_line(r, ctx); | 1199 u = r->upstream; |
1200 | |
1201 rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); | |
1209 | 1202 |
1210 if (rc == NGX_AGAIN) { | 1203 if (rc == NGX_AGAIN) { |
1211 return rc; | 1204 return rc; |
1212 } | 1205 } |
1213 | 1206 |
1214 u = r->upstream; | 1207 if (rc == NGX_ERROR) { |
1215 | |
1216 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | |
1217 | 1208 |
1218 #if (NGX_HTTP_CACHE) | 1209 #if (NGX_HTTP_CACHE) |
1219 | 1210 |
1220 if (r->cache) { | 1211 if (r->cache) { |
1221 r->http_version = NGX_HTTP_VERSION_9; | 1212 r->http_version = NGX_HTTP_VERSION_9; |
1238 | 1229 |
1239 return NGX_OK; | 1230 return NGX_OK; |
1240 } | 1231 } |
1241 | 1232 |
1242 if (u->state) { | 1233 if (u->state) { |
1243 u->state->status = ctx->status; | 1234 u->state->status = ctx->status.code; |
1244 } | 1235 } |
1245 | 1236 |
1246 u->headers_in.status_n = ctx->status; | 1237 u->headers_in.status_n = ctx->status.code; |
1247 | 1238 |
1248 u->headers_in.status_line.len = ctx->status_end - ctx->status_start; | 1239 len = ctx->status.end - ctx->status.start; |
1249 u->headers_in.status_line.data = ngx_pnalloc(r->pool, | 1240 u->headers_in.status_line.len = len; |
1250 u->headers_in.status_line.len); | 1241 |
1242 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); | |
1251 if (u->headers_in.status_line.data == NULL) { | 1243 if (u->headers_in.status_line.data == NULL) { |
1252 return NGX_ERROR; | 1244 return NGX_ERROR; |
1253 } | 1245 } |
1254 | 1246 |
1255 ngx_memcpy(u->headers_in.status_line.data, ctx->status_start, | 1247 ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); |
1256 u->headers_in.status_line.len); | |
1257 | 1248 |
1258 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1249 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1259 "http proxy status %ui \"%V\"", | 1250 "http proxy status %ui \"%V\"", |
1260 u->headers_in.status_n, &u->headers_in.status_line); | 1251 u->headers_in.status_n, &u->headers_in.status_line); |
1261 | 1252 |
1262 u->process_header = ngx_http_proxy_process_header; | 1253 u->process_header = ngx_http_proxy_process_header; |
1263 | 1254 |
1264 return ngx_http_proxy_process_header(r); | 1255 return ngx_http_proxy_process_header(r); |
1265 } | |
1266 | |
1267 | |
1268 static ngx_int_t | |
1269 ngx_http_proxy_parse_status_line(ngx_http_request_t *r, | |
1270 ngx_http_proxy_ctx_t *ctx) | |
1271 { | |
1272 u_char ch; | |
1273 u_char *p; | |
1274 ngx_http_upstream_t *u; | |
1275 enum { | |
1276 sw_start = 0, | |
1277 sw_H, | |
1278 sw_HT, | |
1279 sw_HTT, | |
1280 sw_HTTP, | |
1281 sw_first_major_digit, | |
1282 sw_major_digit, | |
1283 sw_first_minor_digit, | |
1284 sw_minor_digit, | |
1285 sw_status, | |
1286 sw_space_after_status, | |
1287 sw_status_text, | |
1288 sw_almost_done | |
1289 } state; | |
1290 | |
1291 u = r->upstream; | |
1292 | |
1293 state = r->state; | |
1294 | |
1295 for (p = u->buffer.pos; p < u->buffer.last; p++) { | |
1296 ch = *p; | |
1297 | |
1298 switch (state) { | |
1299 | |
1300 /* "HTTP/" */ | |
1301 case sw_start: | |
1302 switch (ch) { | |
1303 case 'H': | |
1304 state = sw_H; | |
1305 break; | |
1306 default: | |
1307 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1308 } | |
1309 break; | |
1310 | |
1311 case sw_H: | |
1312 switch (ch) { | |
1313 case 'T': | |
1314 state = sw_HT; | |
1315 break; | |
1316 default: | |
1317 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1318 } | |
1319 break; | |
1320 | |
1321 case sw_HT: | |
1322 switch (ch) { | |
1323 case 'T': | |
1324 state = sw_HTT; | |
1325 break; | |
1326 default: | |
1327 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1328 } | |
1329 break; | |
1330 | |
1331 case sw_HTT: | |
1332 switch (ch) { | |
1333 case 'P': | |
1334 state = sw_HTTP; | |
1335 break; | |
1336 default: | |
1337 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1338 } | |
1339 break; | |
1340 | |
1341 case sw_HTTP: | |
1342 switch (ch) { | |
1343 case '/': | |
1344 state = sw_first_major_digit; | |
1345 break; | |
1346 default: | |
1347 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1348 } | |
1349 break; | |
1350 | |
1351 /* the first digit of major HTTP version */ | |
1352 case sw_first_major_digit: | |
1353 if (ch < '1' || ch > '9') { | |
1354 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1355 } | |
1356 | |
1357 state = sw_major_digit; | |
1358 break; | |
1359 | |
1360 /* the major HTTP version or dot */ | |
1361 case sw_major_digit: | |
1362 if (ch == '.') { | |
1363 state = sw_first_minor_digit; | |
1364 break; | |
1365 } | |
1366 | |
1367 if (ch < '0' || ch > '9') { | |
1368 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1369 } | |
1370 | |
1371 break; | |
1372 | |
1373 /* the first digit of minor HTTP version */ | |
1374 case sw_first_minor_digit: | |
1375 if (ch < '0' || ch > '9') { | |
1376 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1377 } | |
1378 | |
1379 state = sw_minor_digit; | |
1380 break; | |
1381 | |
1382 /* the minor HTTP version or the end of the request line */ | |
1383 case sw_minor_digit: | |
1384 if (ch == ' ') { | |
1385 state = sw_status; | |
1386 break; | |
1387 } | |
1388 | |
1389 if (ch < '0' || ch > '9') { | |
1390 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1391 } | |
1392 | |
1393 break; | |
1394 | |
1395 /* HTTP status code */ | |
1396 case sw_status: | |
1397 if (ch == ' ') { | |
1398 break; | |
1399 } | |
1400 | |
1401 if (ch < '0' || ch > '9') { | |
1402 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1403 } | |
1404 | |
1405 ctx->status = ctx->status * 10 + ch - '0'; | |
1406 | |
1407 if (++ctx->status_count == 3) { | |
1408 state = sw_space_after_status; | |
1409 ctx->status_start = p - 2; | |
1410 } | |
1411 | |
1412 break; | |
1413 | |
1414 /* space or end of line */ | |
1415 case sw_space_after_status: | |
1416 switch (ch) { | |
1417 case ' ': | |
1418 state = sw_status_text; | |
1419 break; | |
1420 case '.': /* IIS may send 403.1, 403.2, etc */ | |
1421 state = sw_status_text; | |
1422 break; | |
1423 case CR: | |
1424 state = sw_almost_done; | |
1425 break; | |
1426 case LF: | |
1427 goto done; | |
1428 default: | |
1429 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1430 } | |
1431 break; | |
1432 | |
1433 /* any text until end of line */ | |
1434 case sw_status_text: | |
1435 switch (ch) { | |
1436 case CR: | |
1437 state = sw_almost_done; | |
1438 | |
1439 break; | |
1440 case LF: | |
1441 goto done; | |
1442 } | |
1443 break; | |
1444 | |
1445 /* end of status line */ | |
1446 case sw_almost_done: | |
1447 ctx->status_end = p - 1; | |
1448 switch (ch) { | |
1449 case LF: | |
1450 goto done; | |
1451 default: | |
1452 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1453 } | |
1454 } | |
1455 } | |
1456 | |
1457 u->buffer.pos = p; | |
1458 r->state = state; | |
1459 | |
1460 return NGX_AGAIN; | |
1461 | |
1462 done: | |
1463 | |
1464 u->buffer.pos = p + 1; | |
1465 | |
1466 if (ctx->status_end == NULL) { | |
1467 ctx->status_end = p; | |
1468 } | |
1469 | |
1470 r->state = sw_start; | |
1471 | |
1472 return NGX_OK; | |
1473 } | 1256 } |
1474 | 1257 |
1475 | 1258 |
1476 static ngx_int_t | 1259 static ngx_int_t |
1477 ngx_http_proxy_process_header(ngx_http_request_t *r) | 1260 ngx_http_proxy_process_header(ngx_http_request_t *r) |