Re: PHP 4.0 Bug #5040 Updated: Support for persistent HTTP/1.0 connections

From: Date: Sat, 08 Jul 2000 11:58:22 +0000
Subject: Re: PHP 4.0 Bug #5040 Updated: Support for persistent HTTP/1.0 connections
References: 1  Groups: php.dev 
Request: Send a blank email to php-dev+get-23864@lists.php.net to get a copy of this message
At 19:43 08.07.00 -0000, you wrote: >ID: 5040 >User Update by: mnot@pobox.com >Status: Open >Bug Type: Feature/Change Request >Description: Support for persistent HTTP/1.0 connections > hi, i am using since 4.0RC1 a patch which adresses the original problem of generating the http-content-length header. my reason for doing this was that we are developing applications that run behind http-accelerators (squid) which need the content-length-headers for storing the objects. idea: the main idea is based on the observation that the function php_ub_body_write() is only called before any headers are out and output-buffering is active. if the output layer knows that there is no more data following this function could easily generate the content-length header. implementation: to signal the condition "no more data following" i use the new parameter-value 2 for php_end_ob_buffering() and defined a new flag "no_more_data" in php_output_globals. the function php_ub_body_write() is rewritten because we need the final length (after session_adapt_uris) before printing the headers. in real it's no complete rewrite but an integration of php_ub_write_no_header(). in php_ub_body_write you have 2 possibilities: - generate the "Content-Length: " header - storing the calculated length for later generation i have successfully tested the first possibility, but decided later to use the second because i wanted to call the apache-funtion set_content_length(r,length) instead of generating the header. so i defined a new field content_length in the sapi_headers_struct for storing the information. todo: all sapi modules which use the send_headers-hook must now generate the header or use a server-specific function to generate the content-length. i have done this *only for apache* and this runs fine in a production environment. i also generate the header in sapi_send_headers() for cgi but this is not intensivly tested. to use this new feature there are some other minor changes needed, because you must not call php_header before calling php_end_ob_buffering(). so the old used order sapi_send_headers(); php_end_ob_buffering(1); should now be php_end_ob_buffering(2); /* no more data */ if (!SG(headers_sent)) { sapi_send_headers(); } /* force output of headers */ there are also some modules like standard/file.c, gd/gd.c ans others which call php_header() to decide if they should generate output or not. If this modules are no longer calling php_header() then a HEAD-request also gets a content-length. regards Marc and now the patch: diff -ur php-4.0.1-orig/ext/standard/output.c php-4.0.1/ext/standard/output.c --- php-4.0.1-orig/ext/standard/output.c Sat Jun 24 15:27:34 2000 +++ php-4.0.1/ext/standard/output.c Tue Jul 4 08:37:46 2000 @@ -52,6 +52,7 @@ OG(ob_block_size) = 0; OG(ob_text_length) = 0; OG(implicit_flush) = 0; + OG(no_more_data) = 0; OG(output_start_filename) = NULL; OG(output_start_lineno) = 0; } @@ -76,6 +77,8 @@ OG(ob_buffer) = NULL; OG(php_body_write) = php_ub_body_write; OG(php_header_write) = sapi_module.ub_write; + + OG(no_more_data) = 0; } PHPAPI int php_body_write(const char *str, uint str_length) @@ -109,9 +112,13 @@ if (!OG(ob_buffer)) { return; } + if (SG(headers_sent) && !SG(request_info).headers_only) { OG(php_body_write) = php_ub_body_write_no_header; } else { + if (send_buffer==2) { + OG(no_more_data) = 1; /* the buffer contains the complete data */ + } OG(php_body_write) = php_ub_body_write; } if (send_buffer) { @@ -283,13 +290,23 @@ static int php_ub_body_write(const char *str, uint str_length) { + char *newstr = NULL; + uint new_length=0; int result = 0; SLS_FETCH(); OLS_FETCH(); - if (SG(request_info).headers_only) { - zend_bailout(); + session_adapt_uris(str, str_length, &newstr, &new_length); + + if (newstr) { + str = newstr; + str_length = new_length; + } + + if (OG(no_more_data)) { + SG(sapi_headers).content_length = str_length; } + if (php_header()) { if (zend_is_compiling()) { CLS_FETCH(); @@ -304,7 +321,15 @@ } OG(php_body_write) = php_ub_body_write_no_header; - result = php_ub_body_write_no_header(str, str_length); + result = OG(php_header_write)(str, str_length); + } + + if (newstr) { + free(newstr); + } + + if (SG(request_info).headers_only) { + zend_bailout(); } return result; diff -ur php-4.0.1-orig/ext/standard/php_output.h php-4.0.1/ext/standard/php_output.h --- php-4.0.1-orig/ext/standard/php_output.h Sat Jun 24 15:27:34 2000 +++ php-4.0.1/ext/standard/php_output.h Mon Jul 3 08:44:39 2000 @@ -49,6 +49,7 @@ uint ob_block_size; uint ob_text_length; unsigned char implicit_flush; + unsigned char no_more_data; char *output_start_filename; int output_start_lineno; } php_output_globals; diff -ur php-4.0.1-orig/main/SAPI.c php-4.0.1/main/SAPI.c --- php-4.0.1-orig/main/SAPI.c Fri Jun 23 15:05:06 2000 +++ php-4.0.1/main/SAPI.c Mon Jul 3 08:30:25 2000 @@ -264,6 +264,7 @@ SG(sapi_headers).http_response_code = 200; SG(sapi_headers).http_status_line = NULL; + SG(sapi_headers).content_length = 0; SG(headers_sent) = 0; SG(read_post_bytes) = 0; SG(request_info).post_data = NULL; @@ -475,6 +476,14 @@ sapi_get_default_content_type_header(&default_header SLS_CC); sapi_module.send_header(&default_header, SG(server_context)); sapi_free_header(&default_header); + } + if (SG(sapi_headers).content_length) { + sapi_header_struct content_length; + + content_length.header = emalloc(64); + content_length.header_len = snprintf(content_length.header, 63, "Content-Length: %u", SG(sapi_headers).content_length); + sapi_module.send_header(&content_length, SG(server_context)); + efree(content_length.header); } sapi_module.send_header(NULL, SG(server_context)); SG(headers_sent) = 1; diff -ur php-4.0.1-orig/main/SAPI.h php-4.0.1/main/SAPI.h --- php-4.0.1-orig/main/SAPI.h Mon Jun 26 20:05:49 2000 +++ php-4.0.1/main/SAPI.h Mon Jul 3 08:30:25 2000 @@ -49,6 +49,7 @@ int http_response_code; unsigned char send_default_content_type; char *http_status_line; + uint content_length; } sapi_headers_struct; diff -ur php-4.0.1-orig/main/main.c php-4.0.1/main/main.c --- php-4.0.1-orig/main/main.c Mon Jun 26 19:11:28 2000 +++ php-4.0.1/main/main.c Mon Jul 3 08:46:30 2000 @@ -648,8 +648,8 @@ return; } - sapi_send_headers(); - php_end_ob_buffering(SG(request_info).headers_only?0:1); + php_end_ob_buffering(2); /* no more data */ + if (!SG(headers_sent)) { sapi_send_headers(); } /* force output of headers */ php_call_shutdown_functions(); diff -ur php-4.0.1-orig/sapi/apache/mod_php4.c php-4.0.1/sapi/apache/mod_php4.c --- php-4.0.1-orig/sapi/apache/mod_php4.c Wed Jun 28 20:27:13 2000 +++ php-4.0.1/sapi/apache/mod_php4.c Mon Jul 3 08:30:26 2000 @@ -227,12 +227,18 @@ int sapi_apache_send_headers(sapi_headers_struct *sapi_headers SLS_DC) { - if(SG(server_context) == NULL) { /* server_context is not here anymore */ + request_rec *r = (request_rec *) SG(server_context); + + if(r == NULL) { /* server_context is not here anymore */ return SAPI_HEADER_SEND_FAILED; } - ((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code; - send_http_header((request_rec *) SG(server_context)); + r->status = SG(sapi_headers).http_response_code; + + if (SG(sapi_headers).content_length) { + set_content_length(r, SG(sapi_headers).content_length); + } + send_http_header(r); return SAPI_HEADER_SENT_SUCCESSFULLY; } diff -ur php-4.0.1-orig/sapi/apache/sapi_apache.c php-4.0.1/sapi/apache/sapi_apache.c --- php-4.0.1-orig/sapi/apache/sapi_apache.c Tue Jun 6 01:21:57 2000 +++ php-4.0.1/sapi/apache/sapi_apache.c Mon Jul 3 08:46:20 2000 @@ -93,8 +93,9 @@ (void) php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); } - php_header(); /* Make sure headers have been sent */ - php_end_ob_buffering(1); + php_end_ob_buffering(2); /* no more data */ + if (!SG(headers_sent)) { sapi_send_headers(); } /* force output of headers */ + return (OK); } diff -ur php-4.0.1-orig/sapi/cgi/cgi_main.c php-4.0.1/sapi/cgi/cgi_main.c --- php-4.0.1-orig/sapi/cgi/cgi_main.c Mon Jun 26 20:05:51 2000 +++ php-4.0.1/sapi/cgi/cgi_main.c Tue Jul 4 09:14:11 2000 @@ -683,8 +683,8 @@ #endif } - php_header(); /* Make sure headers have been sent */ - + php_end_ob_buffering(2); /* no more data */ + if (!SG(headers_sent)) { sapi_send_headers(); } /* force output of headers */ if (SG(request_info).path_translated) { persist_alloc(SG(request_info).path_translated); ------------------------------------------------------------------------------ Marc Pohl, Service-Center-Infrastruktur, Westdeutscher Rundfunk, D-50600 Koeln marc.pohl@wdr.de, +49 221 220 8618, http://www.wdr.de/ ------------------------------------------------------------------------------

« previous php.dev (#23864) next »