fielding 97/05/14 12:22:57
Modified: src CHANGES httpd.h alloc.h http_request.c http_protocol.c Log: Restore the semantics of headers_out headers sent only with 200..299 and 304 responses err_headers_out headers sent with all responses Moved the prior changes from the die() function to send_error_response() where they belong, and supplemented those with the other values that need to be reset. It also avoids the overhead of copying tables if err_headers_out is empty (the usual case), fixes a bug with assbackwards and 204/304, and removes a bit of code that should not be generating a Cache-Control header field even if r->no_cache is set. Reviewed by: Dean Gaudet Revision Changes Path 1.275 +6 -1 apache/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache/src/CHANGES,v retrieving revision 1.274 retrieving revision 1.275 diff -C3 -r1.274 -r1.275 *** CHANGES 1997/05/13 04:01:49 1.274 --- CHANGES 1997/05/14 19:22:50 1.275 *************** *** 2,8 **** *) If the lookup for a DirectoryIndex name with content negotiation has found matching variants, but none are acceptable, return the ! negotiation result if there are no more DirectoryIndex names lookup. [Petr Lampa and Roy Fielding] *) If a soft_timeout occurs after keepalive is set, then the main child --- 2,8 ---- *) If the lookup for a DirectoryIndex name with content negotiation has found matching variants, but none are acceptable, return the ! negotiation result if there are no more DirectoryIndex names to lookup. [Petr Lampa and Roy Fielding] *) If a soft_timeout occurs after keepalive is set, then the main child *************** *** 22,27 **** --- 22,32 ---- reset the content_language(s) and content_encoding of the response before generating or redirecting to an error message, since the new message will have its own Content-* definitions. [Dean Gaudet] + + *) Restored the semantics of headers_out (headers sent only with 200..299 + and 304 responses) and err_headers_out (headers sent with all responses). + Avoid the overhead of copying tables if err_headers_out is empty + (the usual case). [Roy Fielding] *) Fixed a couple places where a check for the default Content-Type was not properly checking both the value configured by the DefaultType 1.104 +1 -1 apache/src/httpd.h Index: httpd.h =================================================================== RCS file: /export/home/cvs/apache/src/httpd.h,v retrieving revision 1.103 retrieving revision 1.104 diff -C3 -r1.103 -r1.104 *** httpd.h 1997/05/08 11:27:28 1.103 --- httpd.h 1997/05/14 19:22:51 1.104 *************** *** 474,480 **** * write modules to add to that environment. * * The difference between headers_out and err_headers_out is that the ! * latter persist across internal redirects * (so the headers printed for ErrorDocument handlers will have them). * * The 'notes' table is for notes from one module to another, with no --- 474,480 ---- * write modules to add to that environment. * * The difference between headers_out and err_headers_out is that the ! * latter are printed even on error, and persist across internal redirects * (so the headers printed for ErrorDocument handlers will have them). * * The 'notes' table is for notes from one module to another, with no 1.20 +2 -0 apache/src/alloc.h Index: alloc.h =================================================================== RCS file: /export/home/cvs/apache/src/alloc.h,v retrieving revision 1.19 retrieving revision 1.20 diff -C3 -r1.19 -r1.20 *** alloc.h 1997/04/24 23:35:19 1.19 --- alloc.h 1997/05/14 19:22:52 1.20 *************** *** 156,161 **** --- 156,163 ---- array_header *table_elts (table *); + #define is_empty_table(t) (((t) == NULL)||((t)->nelts == 0)) + /* routines to remember allocation of other sorts of things... * generic interface first. Note that we want to have two separate * cleanup functions in the general case, one for exec() preparation, 1.50 +0 -10 apache/src/http_request.c Index: http_request.c =================================================================== RCS file: /export/home/cvs/apache/src/http_request.c,v retrieving revision 1.49 retrieving revision 1.50 diff -C3 -r1.49 -r1.50 *** http_request.c 1997/05/11 22:30:37 1.49 --- http_request.c 1997/05/14 19:22:52 1.50 *************** *** 764,779 **** r->status = type; - /* XXX: this is an awful thing to have to do here, in fact there are - * probably other cases that need this attention. Essentially we're - * about to report an error, and if we don't do an internal_redirect - * below then we'll report the error with the wrong headers -- we'll - * use headers belonging to the original request. - */ - r->content_language = NULL; - r->content_languages = NULL; - r->content_encoding = NULL; - /* Two types of custom redirects --- plain text, and URLs. * Plain text has a leading '"', so the URL code, here, is triggered * on its absence --- 764,769 ---- 1.121 +62 -45 apache/src/http_protocol.c Index: http_protocol.c =================================================================== RCS file: /export/home/cvs/apache/src/http_protocol.c,v retrieving revision 1.120 retrieving revision 1.121 diff -C3 -r1.120 -r1.121 *** http_protocol.c 1997/05/11 22:30:37 1.120 --- http_protocol.c 1997/05/14 19:22:53 1.121 *************** *** 1186,1192 **** * header field tables into a single table. If we don't do this, our * later attempts to set or unset a given fieldname might be bypassed. */ ! r->headers_out=overlay_tables(r->pool, r->err_headers_out, r->headers_out); hard_timeout("send headers", r); --- 1186,1194 ---- * header field tables into a single table. If we don't do this, our * later attempts to set or unset a given fieldname might be bypassed. */ ! if (!is_empty_table(r->err_headers_out)) ! r->headers_out = overlay_tables(r->pool, r->err_headers_out, ! r->headers_out); hard_timeout("send headers", r); *************** *** 1223,1237 **** /* Control cachability for non-cachable responses if not already set * by some other part of the server configuration. */ ! if (r->no_cache) { ! if ((r->proto_num >= 1001) && ! !table_get(r->headers_out, "Cache-Control")) ! table_add(r->headers_out, "Cache-Control", "private"); ! ! if (!table_get(r->headers_out, "Expires")) ! table_add(r->headers_out, "Expires", ! gm_timestr_822(r->pool, r->request_time)); ! } /* Send the entire table of header fields, terminated by an empty line. */ --- 1225,1233 ---- /* Control cachability for non-cachable responses if not already set * by some other part of the server configuration. */ ! if (r->no_cache && !table_get(r->headers_out, "Expires")) ! table_add(r->headers_out, "Expires", ! gm_timestr_822(r->pool, r->request_time)); /* Send the entire table of header fields, terminated by an empty line. */ *************** *** 1643,1648 **** --- 1639,1650 ---- return bflush(r->connection->client); } + /* We should have named this send_canned_response, since it is used for any + * response that can be generated by the server from the request record. + * This includes all 204 (no content), 3xx (redirect), 4xx (client error), + * and 5xx (server error) messages that have not been redirected to another + * handler via the ErrorDocument feature. + */ void send_error_response (request_rec *r, int recursive_error) { BUFF *fd = r->connection->client; *************** *** 1651,1700 **** char *custom_response; char *location = pstrdup(r->pool, table_get(r->headers_out, "Location")); ! if (!r->assbackwards) { ! ! /* For non-error statuses (2xx and 3xx), send out all the normal ! * headers unless it is a 304. Don't send a Location unless its ! * a redirect status (3xx). ! */ ! if (status == HTTP_NOT_MODIFIED) { ! r->headers_out = overlay_tables(r->pool, r->err_headers_out, ! r->headers_out); ! hard_timeout("send 304", r); ! ! basic_http_header(r); ! set_keepalive(r); ! ! table_do((int (*)(void *, const char *, const char *))send_header_field, ! (void *)r, r->headers_out, ! "Connection", ! "Keep-Alive", ! "ETag", ! "Content-Location", ! "Expires", ! "Cache-Control", ! "Vary", ! "Warning", ! "WWW-Authenticate", ! NULL); ! terminate_header(r->connection->client); ! kill_timeout(r); ! return; ! } if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED)) table_set(r->headers_out, "Allow", make_allow(r)); - if (!is_HTTP_REDIRECT(status)) - table_unset(r->headers_out, "Location"); - - r->content_type = "text/html"; send_http_header(r); ! if (r->header_only || (status == HTTP_NO_CONTENT)) { finalize_request_protocol(r); return; } --- 1653,1717 ---- char *custom_response; char *location = pstrdup(r->pool, table_get(r->headers_out, "Location")); ! /* We need to special-case the handling of 204 and 304 responses, ! * since they have specific HTTP requirements and do not include a ! * message body. Note that being assbackwards here is not an option. ! */ ! if (status == HTTP_NOT_MODIFIED) { ! if (!is_empty_table(r->err_headers_out)) ! r->headers_out = overlay_tables(r->pool, r->err_headers_out, ! r->headers_out); ! hard_timeout("send 304", r); ! ! basic_http_header(r); ! set_keepalive(r); ! ! table_do((int (*)(void *, const char *, const char *))send_header_field, ! (void *)r, r->headers_out, ! "Connection", ! "Keep-Alive", ! "ETag", ! "Content-Location", ! "Expires", ! "Cache-Control", ! "Vary", ! "Warning", ! "WWW-Authenticate", ! NULL); ! terminate_header(r->connection->client); ! kill_timeout(r); ! return; ! } ! if (status == HTTP_NO_CONTENT) { ! send_http_header(r); ! finalize_request_protocol(r); ! return; ! } ! ! if (!r->assbackwards) { ! ! /* For all HTTP/1.x responses for which we generate the message, ! * we need to avoid inheriting the "normal status" header fields ! * that may have been set by the request handler before the ! * error or redirect. ! */ ! r->headers_out = r->err_headers_out; ! r->err_headers_out = NULL; ! r->content_language = NULL; ! r->content_languages = NULL; ! r->content_encoding = NULL; ! r->clength = 0; ! r->content_type = "text/html"; if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED)) table_set(r->headers_out, "Allow", make_allow(r)); send_http_header(r); ! if (r->header_only) { finalize_request_protocol(r); return; }