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)