@@ -1300,107 +1300,10 @@ typedef struct header_filter_ctx {
13001300 int headers_sent ;
13011301} header_filter_ctx ;
13021302
1303- AP_CORE_DECLARE_NONSTD (apr_status_t ) ap_http_header_filter (ap_filter_t * f ,
1304- apr_bucket_brigade * b )
1303+ static void merge_response_headers (request_rec * r , const char * * protocol )
13051304{
1306- request_rec * r = f -> r ;
1307- conn_rec * c = r -> connection ;
1308- const char * clheader ;
1309- int header_only = (r -> header_only || AP_STATUS_IS_HEADER_ONLY (r -> status ));
1310- const char * protocol = NULL ;
1311- apr_bucket * e ;
1312- apr_bucket_brigade * b2 ;
1313- header_struct h ;
1314- header_filter_ctx * ctx = f -> ctx ;
1315- const char * ctype ;
1316- ap_bucket_error * eb = NULL ;
1317- apr_status_t rv = APR_SUCCESS ;
1318- int recursive_error = 0 ;
1319-
1320- AP_DEBUG_ASSERT (!r -> main );
1321-
1322- if (!ctx ) {
1323- ctx = f -> ctx = apr_pcalloc (r -> pool , sizeof (header_filter_ctx ));
1324- }
1325- else if (ctx -> headers_sent ) {
1326- /* Eat body if response must not have one. */
1327- if (header_only ) {
1328- /* Still next filters may be waiting for EOS, so pass it (alone)
1329- * when encountered and be done with this filter.
1330- */
1331- e = APR_BRIGADE_LAST (b );
1332- if (e != APR_BRIGADE_SENTINEL (b ) && APR_BUCKET_IS_EOS (e )) {
1333- APR_BUCKET_REMOVE (e );
1334- apr_brigade_cleanup (b );
1335- APR_BRIGADE_INSERT_HEAD (b , e );
1336- ap_remove_output_filter (f );
1337- rv = ap_pass_brigade (f -> next , b );
1338- }
1339- apr_brigade_cleanup (b );
1340- return rv ;
1341- }
1342- }
1343-
1344- for (e = APR_BRIGADE_FIRST (b );
1345- e != APR_BRIGADE_SENTINEL (b );
1346- e = APR_BUCKET_NEXT (e ))
1347- {
1348- if (AP_BUCKET_IS_ERROR (e ) && !eb ) {
1349- eb = e -> data ;
1350- continue ;
1351- }
1352- /*
1353- * If we see an EOC bucket it is a signal that we should get out
1354- * of the way doing nothing.
1355- */
1356- if (AP_BUCKET_IS_EOC (e )) {
1357- ap_remove_output_filter (f );
1358- return ap_pass_brigade (f -> next , b );
1359- }
1360- }
1361-
1362- if (!ctx -> headers_sent && !check_headers (r )) {
1363- /* We may come back here from ap_die() below,
1364- * so clear anything from this response.
1365- */
1366- apr_table_clear (r -> headers_out );
1367- apr_table_clear (r -> err_headers_out );
1368- r -> content_type = r -> content_encoding = NULL ;
1369- r -> content_languages = NULL ;
1370- r -> clength = r -> chunked = 0 ;
1371- apr_brigade_cleanup (b );
1372-
1373- /* Don't recall ap_die() if we come back here (from its own internal
1374- * redirect or error response), otherwise we can end up in infinite
1375- * recursion; better fall through with 500, minimal headers and an
1376- * empty body (EOS only).
1377- */
1378- if (!check_headers_recursion (r )) {
1379- ap_die (HTTP_INTERNAL_SERVER_ERROR , r );
1380- return AP_FILTER_ERROR ;
1381- }
1382- r -> status = HTTP_INTERNAL_SERVER_ERROR ;
1383- e = ap_bucket_eoc_create (c -> bucket_alloc );
1384- APR_BRIGADE_INSERT_TAIL (b , e );
1385- e = apr_bucket_eos_create (c -> bucket_alloc );
1386- APR_BRIGADE_INSERT_TAIL (b , e );
1387- ap_set_content_length (r , 0 );
1388- recursive_error = 1 ;
1389- }
1390- else if (eb ) {
1391- int status ;
1392- status = eb -> status ;
1393- apr_brigade_cleanup (b );
1394- ap_die (status , r );
1395- return AP_FILTER_ERROR ;
1396- }
1397-
1398- if (r -> assbackwards ) {
1399- r -> sent_bodyct = 1 ;
1400- ap_remove_output_filter (f );
1401- rv = ap_pass_brigade (f -> next , b );
1402- goto out ;
1403- }
1305+ const char * ctype = NULL ;
1306+ const char * clheader = NULL ;
14041307
14051308 /*
14061309 * Now that we are ready to send a response, we need to combine the two
@@ -1430,6 +1333,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
14301333 fixup_vary (r );
14311334 }
14321335
1336+ /* determine the protocol and whether we should use keepalives. */
1337+ basic_http_header_check (r , protocol );
1338+ ap_set_keepalive (r );
14331339
14341340 /*
14351341 * Control cachability for non-cacheable responses if not already set by
@@ -1449,10 +1355,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
14491355 apr_table_unset (r -> headers_out , "ETag" );
14501356 }
14511357
1452- /* determine the protocol and whether we should use keepalives. */
1453- basic_http_header_check (r , & protocol );
1454- ap_set_keepalive (r );
1455-
14561358 /* 204/304 responses don't have content related headers */
14571359 if (AP_STATUS_IS_HEADER_ONLY (r -> status )) {
14581360 apr_table_unset (r -> headers_out , "Transfer-Encoding" );
@@ -1513,30 +1415,136 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
15131415 && !strcmp (clheader , "0" )) {
15141416 apr_table_unset (r -> headers_out , "Content-Length" );
15151417 }
1418+ }
15161419
1517- b2 = apr_brigade_create (r -> pool , c -> bucket_alloc );
1518- basic_http_header (r , b2 , protocol );
1519-
1520- h .pool = r -> pool ;
1521- h .bb = b2 ;
1420+ AP_CORE_DECLARE_NONSTD (apr_status_t ) ap_http_header_filter (ap_filter_t * f ,
1421+ apr_bucket_brigade * b )
1422+ {
1423+ request_rec * r = f -> r ;
1424+ conn_rec * c = r -> connection ;
1425+ int header_only = (r -> header_only || AP_STATUS_IS_HEADER_ONLY (r -> status ));
1426+ apr_bucket * e ;
1427+ apr_bucket_brigade * b2 ;
1428+ header_struct h ;
1429+ header_filter_ctx * ctx = f -> ctx ;
1430+ ap_bucket_error * eb = NULL ;
1431+ apr_status_t rv = APR_SUCCESS ;
1432+ int recursive_error = 0 ;
1433+ const char * protocol ;
15221434
1523- send_all_header_fields ( & h , r );
1435+ AP_DEBUG_ASSERT (! r -> main );
15241436
1525- terminate_header (b2 );
1437+ if (!ctx ) {
1438+ ctx = f -> ctx = apr_pcalloc (r -> pool , sizeof (header_filter_ctx ));
1439+ }
1440+ else if (ctx -> headers_sent ) {
1441+ /* Eat body if response must not have one. */
1442+ if (header_only ) {
1443+ /* Still next filters may be waiting for EOS, so pass it (alone)
1444+ * when encountered and be done with this filter.
1445+ */
1446+ e = APR_BRIGADE_LAST (b );
1447+ if (e != APR_BRIGADE_SENTINEL (b ) && APR_BUCKET_IS_EOS (e )) {
1448+ APR_BUCKET_REMOVE (e );
1449+ apr_brigade_cleanup (b );
1450+ APR_BRIGADE_INSERT_HEAD (b , e );
1451+ ap_remove_output_filter (f );
1452+ rv = ap_pass_brigade (f -> next , b );
1453+ }
1454+ apr_brigade_cleanup (b );
1455+ return rv ;
1456+ }
1457+ }
15261458
1527- if (header_only ) {
1528- e = APR_BRIGADE_LAST (b );
1529- if (e != APR_BRIGADE_SENTINEL (b ) && APR_BUCKET_IS_EOS (e )) {
1530- APR_BUCKET_REMOVE (e );
1531- APR_BRIGADE_INSERT_TAIL (b2 , e );
1459+ for (e = APR_BRIGADE_FIRST (b );
1460+ e != APR_BRIGADE_SENTINEL (b );
1461+ e = APR_BUCKET_NEXT (e ))
1462+ {
1463+ if (AP_BUCKET_IS_ERROR (e ) && !eb ) {
1464+ eb = e -> data ;
1465+ continue ;
1466+ }
1467+ /*
1468+ * If we see an EOC bucket it is a signal that we should get out
1469+ * of the way doing nothing.
1470+ */
1471+ if (AP_BUCKET_IS_EOC (e )) {
15321472 ap_remove_output_filter (f );
1473+ return ap_pass_brigade (f -> next , b );
1474+ }
1475+ }
1476+
1477+ if (!ctx -> headers_sent ) {
1478+ merge_response_headers (r , & protocol );
1479+ if (!check_headers (r )) {
1480+ /* We may come back here from ap_die() below,
1481+ * so clear anything from this response.
1482+ */
1483+ apr_table_clear (r -> headers_out );
1484+ apr_table_clear (r -> err_headers_out );
1485+ r -> content_type = r -> content_encoding = NULL ;
1486+ r -> content_languages = NULL ;
1487+ r -> clength = r -> chunked = 0 ;
1488+ apr_brigade_cleanup (b );
1489+
1490+ /* Don't recall ap_die() if we come back here (from its own internal
1491+ * redirect or error response), otherwise we can end up in infinite
1492+ * recursion; better fall through with 500, minimal headers and an
1493+ * empty body (EOS only).
1494+ */
1495+ if (!check_headers_recursion (r )) {
1496+ ap_die (HTTP_INTERNAL_SERVER_ERROR , r );
1497+ return AP_FILTER_ERROR ;
1498+ }
1499+ r -> status = HTTP_INTERNAL_SERVER_ERROR ;
1500+ e = ap_bucket_eoc_create (c -> bucket_alloc );
1501+ APR_BRIGADE_INSERT_TAIL (b , e );
1502+ e = apr_bucket_eos_create (c -> bucket_alloc );
1503+ APR_BRIGADE_INSERT_TAIL (b , e );
1504+ ap_set_content_length (r , 0 );
1505+ recursive_error = 1 ;
1506+ }
1507+ else if (eb ) {
1508+ int status ;
1509+ status = eb -> status ;
1510+ apr_brigade_cleanup (b );
1511+ ap_die (status , r );
1512+ return AP_FILTER_ERROR ;
15331513 }
1534- apr_brigade_cleanup (b );
15351514 }
15361515
1537- rv = ap_pass_brigade (f -> next , b2 );
1538- apr_brigade_cleanup (b2 );
1539- ctx -> headers_sent = 1 ;
1516+ if (r -> assbackwards ) {
1517+ r -> sent_bodyct = 1 ;
1518+ ap_remove_output_filter (f );
1519+ rv = ap_pass_brigade (f -> next , b );
1520+ goto out ;
1521+ }
1522+
1523+ if (!ctx -> headers_sent ) {
1524+ b2 = apr_brigade_create (r -> pool , c -> bucket_alloc );
1525+ basic_http_header (r , b2 , protocol );
1526+
1527+ h .pool = r -> pool ;
1528+ h .bb = b2 ;
1529+
1530+ send_all_header_fields (& h , r );
1531+
1532+ terminate_header (b2 );
1533+
1534+ if (header_only ) {
1535+ e = APR_BRIGADE_LAST (b );
1536+ if (e != APR_BRIGADE_SENTINEL (b ) && APR_BUCKET_IS_EOS (e )) {
1537+ APR_BUCKET_REMOVE (e );
1538+ APR_BRIGADE_INSERT_TAIL (b2 , e );
1539+ ap_remove_output_filter (f );
1540+ }
1541+ apr_brigade_cleanup (b );
1542+ }
1543+
1544+ rv = ap_pass_brigade (f -> next , b2 );
1545+ apr_brigade_cleanup (b2 );
1546+ ctx -> headers_sent = 1 ;
1547+ }
15401548
15411549 if (rv != APR_SUCCESS || header_only ) {
15421550 goto out ;
0 commit comments