Re: PHP 4.0 Bug #5040 Updated: Support for persistent HTTP/1.0 connections
| From: | Marc Pohl | 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/
------------------------------------------------------------------------------