mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Connection oriented filters are now stored in the conn_rec instead of the
request_rec. This means that a conn_rec must be supplied when calling ap_add_filter. The reason for this change is that we need to be able to add the core_filter (whether or SSL or not) before we try to read the request. This way, if a request fails, we can actually send the error page back to the client. With this change, we add the core filter to the conn_rec during the pre-connection phase. Submitted by: Ryan Bloom, Jeff Trawick, and Greg Ames git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86392 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -885,6 +885,9 @@ struct conn_rec {
|
|||||||
/** Location to store data read from the client.
|
/** Location to store data read from the client.
|
||||||
* @defvar ap_bucket_brigade *input_data */
|
* @defvar ap_bucket_brigade *input_data */
|
||||||
struct ap_bucket_brigade *input_data;
|
struct ap_bucket_brigade *input_data;
|
||||||
|
/** A list of output filters to be used for this connection
|
||||||
|
* @defvar ap_filter_t *filters */
|
||||||
|
struct ap_filter_t *output_filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Per-vhost config... */
|
/* Per-vhost config... */
|
||||||
|
@@ -332,7 +332,8 @@ API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *r);
|
|||||||
* @param r The request to add this filter for.
|
* @param r The request to add this filter for.
|
||||||
* @deffunc void ap_add_filter(const char *name, request_rec *r)
|
* @deffunc void ap_add_filter(const char *name, request_rec *r)
|
||||||
*/
|
*/
|
||||||
API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r);
|
API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r,
|
||||||
|
conn_rec *c);
|
||||||
|
|
||||||
/* The next two filters are for abstraction purposes only. They could be
|
/* The next two filters are for abstraction purposes only. They could be
|
||||||
* done away with, but that would require that we break modules if we ever
|
* done away with, but that would require that we break modules if we ever
|
||||||
|
@@ -2564,7 +2564,7 @@ static apr_status_t writev_it_all(apr_socket_t *s, struct iovec *vec, int nvec,
|
|||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
/* XXX handle partial writes */
|
/* XXX handle partial writes */
|
||||||
static apr_status_t send_the_file(request_rec *r, apr_file_t *fd,
|
static apr_status_t send_the_file(conn_rec *c, apr_file_t *fd,
|
||||||
apr_hdtr_t *hdtr, apr_off_t offset,
|
apr_hdtr_t *hdtr, apr_off_t offset,
|
||||||
apr_size_t length, apr_size_t *nbytes)
|
apr_size_t length, apr_size_t *nbytes)
|
||||||
{
|
{
|
||||||
@@ -2573,11 +2573,11 @@ static apr_status_t send_the_file(request_rec *r, apr_file_t *fd,
|
|||||||
apr_size_t n = length;
|
apr_size_t n = length;
|
||||||
|
|
||||||
#if APR_HAS_SENDFILE
|
#if APR_HAS_SENDFILE
|
||||||
if (!r->connection->keepalive) {
|
if (!c->keepalive) {
|
||||||
/* Prepare the socket to be reused */
|
/* Prepare the socket to be reused */
|
||||||
flags |= APR_SENDFILE_DISCONNECT_SOCKET;
|
flags |= APR_SENDFILE_DISCONNECT_SOCKET;
|
||||||
}
|
}
|
||||||
rv = apr_sendfile(r->connection->client->bsock,
|
rv = apr_sendfile(c->client->bsock,
|
||||||
fd, /* The file to send */
|
fd, /* The file to send */
|
||||||
hdtr, /* Header and trailer iovecs */
|
hdtr, /* Header and trailer iovecs */
|
||||||
&offset, /* Offset in file to begin sending from */
|
&offset, /* Offset in file to begin sending from */
|
||||||
@@ -2592,6 +2592,7 @@ static apr_status_t send_the_file(request_rec *r, apr_file_t *fd,
|
|||||||
|
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note --- ErrorDocument will now work from .htaccess files.
|
/* Note --- ErrorDocument will now work from .htaccess files.
|
||||||
* The AllowOverride of Fileinfo allows webmasters to turn it off
|
* The AllowOverride of Fileinfo allows webmasters to turn it off
|
||||||
*/
|
*/
|
||||||
@@ -3286,7 +3287,7 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
|
|||||||
ap_bucket_brigade *more = NULL;
|
ap_bucket_brigade *more = NULL;
|
||||||
apr_ssize_t bytes_sent = 0, nbytes = 0;
|
apr_ssize_t bytes_sent = 0, nbytes = 0;
|
||||||
ap_bucket *e;
|
ap_bucket *e;
|
||||||
request_rec *r = f->r;
|
conn_rec *c = f->c;
|
||||||
core_output_filter_ctx_t *ctx = f->ctx;
|
core_output_filter_ctx_t *ctx = f->ctx;
|
||||||
|
|
||||||
apr_ssize_t nvec = 0;
|
apr_ssize_t nvec = 0;
|
||||||
@@ -3299,7 +3300,7 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
|
|||||||
apr_off_t foffset = 0;
|
apr_off_t foffset = 0;
|
||||||
|
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
f->ctx = ctx = apr_pcalloc(r->pool, sizeof(core_output_filter_ctx_t));
|
f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t));
|
||||||
}
|
}
|
||||||
/* If we have a saved brigade, concatenate the new brigade to it */
|
/* If we have a saved brigade, concatenate the new brigade to it */
|
||||||
if (ctx->b) {
|
if (ctx->b) {
|
||||||
@@ -3309,10 +3310,10 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hijack any bytes in BUFF and prepend it to the brigade. */
|
/* Hijack any bytes in BUFF and prepend it to the brigade. */
|
||||||
if (r->connection->client->outcnt) {
|
if (c->client->outcnt) {
|
||||||
e = ap_bucket_create_heap(r->connection->client->outbase,
|
e = ap_bucket_create_heap(c->client->outbase,
|
||||||
r->connection->client->outcnt, 1, NULL);
|
c->client->outcnt, 1, NULL);
|
||||||
r->connection->client->outcnt = 0;
|
c->client->outcnt = 0;
|
||||||
AP_BRIGADE_INSERT_HEAD(b, e);
|
AP_BRIGADE_INSERT_HEAD(b, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3376,10 +3377,10 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
|
|||||||
hdtr.numtrailers = nvec_trailers;
|
hdtr.numtrailers = nvec_trailers;
|
||||||
hdtr.trailers = vec_trailers;
|
hdtr.trailers = vec_trailers;
|
||||||
}
|
}
|
||||||
rv = send_the_file(r, fd, &hdtr, foffset, flen, &bytes_sent);
|
rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rv = writev_it_all(r->connection->client->bsock,
|
rv = writev_it_all(c->client->bsock,
|
||||||
vec, nvec,
|
vec, nvec,
|
||||||
nbytes, &bytes_sent);
|
nbytes, &bytes_sent);
|
||||||
nbytes = 0; /* in case more points to another brigade */
|
nbytes = 0; /* in case more points to another brigade */
|
||||||
@@ -3423,12 +3424,6 @@ static const char *core_method(const request_rec *r)
|
|||||||
static unsigned short core_port(const request_rec *r)
|
static unsigned short core_port(const request_rec *r)
|
||||||
{ return DEFAULT_HTTP_PORT; }
|
{ return DEFAULT_HTTP_PORT; }
|
||||||
|
|
||||||
static int core_post_read_req(request_rec *r)
|
|
||||||
{
|
|
||||||
ap_add_filter("CORE", NULL, r);
|
|
||||||
return DECLINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void core_register_filter(request_rec *r)
|
static void core_register_filter(request_rec *r)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -3439,7 +3434,7 @@ static void core_register_filter(request_rec *r)
|
|||||||
|
|
||||||
for (i = 0; i < conf->filters->nelts; i++) {
|
for (i = 0; i < conf->filters->nelts; i++) {
|
||||||
char *foobar = items[i];
|
char *foobar = items[i];
|
||||||
ap_add_filter(foobar, NULL, r);
|
ap_add_filter(foobar, NULL, r, r->connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3457,7 +3452,6 @@ static void register_hooks(void)
|
|||||||
/* FIXME: I suspect we can eliminate the need for these - Ben */
|
/* FIXME: I suspect we can eliminate the need for these - Ben */
|
||||||
ap_hook_type_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
|
ap_hook_type_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
|
||||||
ap_hook_access_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
|
ap_hook_access_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
|
||||||
ap_hook_post_read_request(core_post_read_req, NULL, NULL, AP_HOOK_REALLY_FIRST);
|
|
||||||
|
|
||||||
/* define the CORE filter, then register a hook to insert it at
|
/* define the CORE filter, then register a hook to insert it at
|
||||||
* request-processing time.
|
* request-processing time.
|
||||||
|
@@ -1244,6 +1244,7 @@ request_rec *ap_read_request(conn_rec *conn)
|
|||||||
|
|
||||||
r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
|
r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
|
||||||
r->the_request = NULL;
|
r->the_request = NULL;
|
||||||
|
r->output_filters = conn->output_filters;
|
||||||
|
|
||||||
#ifdef APACHE_XLATE
|
#ifdef APACHE_XLATE
|
||||||
r->rrx = apr_pcalloc(p, sizeof(struct ap_rr_xlate));
|
r->rrx = apr_pcalloc(p, sizeof(struct ap_rr_xlate));
|
||||||
@@ -2108,8 +2109,8 @@ API_EXPORT(void) ap_send_http_header(request_rec *r)
|
|||||||
if (r->chunked) {
|
if (r->chunked) {
|
||||||
apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
|
apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
|
||||||
apr_table_unset(r->headers_out, "Content-Length");
|
apr_table_unset(r->headers_out, "Content-Length");
|
||||||
ap_add_filter("BUFFER", NULL, r);
|
ap_add_filter("BUFFER", NULL, r, r->connection);
|
||||||
ap_add_filter("CHUNK", NULL, r);
|
ap_add_filter("CHUNK", NULL, r, r->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->byterange > 1) {
|
if (r->byterange > 1) {
|
||||||
|
@@ -217,6 +217,7 @@ CORE_EXPORT(void) ap_process_connection(conn_rec *c)
|
|||||||
int ap_pre_http_connection(conn_rec *c)
|
int ap_pre_http_connection(conn_rec *c)
|
||||||
{
|
{
|
||||||
ap_add_input_filter("CORE_IN", NULL, c);
|
ap_add_input_filter("CORE_IN", NULL, c);
|
||||||
|
ap_add_filter("CORE", NULL, NULL, c);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -148,25 +148,28 @@ API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r)
|
API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r,
|
||||||
|
conn_rec *c)
|
||||||
{
|
{
|
||||||
ap_filter_rec_t *frec = registered_output_filters;
|
ap_filter_rec_t *frec = registered_output_filters;
|
||||||
|
|
||||||
for (; frec != NULL; frec = frec->next) {
|
for (; frec != NULL; frec = frec->next) {
|
||||||
if (!strcasecmp(name, frec->name)) {
|
if (!strcasecmp(name, frec->name)) {
|
||||||
ap_filter_t *f = apr_pcalloc(r->pool, sizeof(*f));
|
apr_pool_t *p = r ? r->pool : c->pool;
|
||||||
|
ap_filter_t *f = apr_pcalloc(p, sizeof(*f));
|
||||||
|
ap_filter_t **outf = r ? &r->output_filters : &c->output_filters;
|
||||||
|
|
||||||
f->frec = frec;
|
f->frec = frec;
|
||||||
f->ctx = ctx;
|
f->ctx = ctx;
|
||||||
f->r = r;
|
f->r = r;
|
||||||
f->c = NULL;
|
f->c = c;
|
||||||
|
|
||||||
if (INSERT_BEFORE(f, r->output_filters)) {
|
if (INSERT_BEFORE(f, *outf)) {
|
||||||
f->next = r->output_filters;
|
f->next = *outf;
|
||||||
r->output_filters = f;
|
*outf = f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ap_filter_t *fscan = r->output_filters;
|
ap_filter_t *fscan = *outf;
|
||||||
while (!INSERT_BEFORE(f, fscan->next))
|
while (!INSERT_BEFORE(f, fscan->next))
|
||||||
fscan = fscan->next;
|
fscan = fscan->next;
|
||||||
f->next = fscan->next;
|
f->next = fscan->next;
|
||||||
@@ -201,7 +204,7 @@ API_EXPORT(apr_status_t) ap_get_brigade(ap_filter_t *next, ap_bucket_brigade *bb
|
|||||||
API_EXPORT(apr_status_t) ap_pass_brigade(ap_filter_t *next, ap_bucket_brigade *bb)
|
API_EXPORT(apr_status_t) ap_pass_brigade(ap_filter_t *next, ap_bucket_brigade *bb)
|
||||||
{
|
{
|
||||||
if (next) {
|
if (next) {
|
||||||
if (AP_BRIGADE_LAST(bb)->type == AP_BUCKET_EOS) {
|
if (AP_BRIGADE_LAST(bb)->type == AP_BUCKET_EOS && next->r) {
|
||||||
next->r->eos_sent = 1;
|
next->r->eos_sent = 1;
|
||||||
}
|
}
|
||||||
return next->frec->filter_func(next, bb);
|
return next->frec->filter_func(next, bb);
|
||||||
@@ -213,12 +216,13 @@ API_EXPORT(void) ap_save_brigade(ap_filter_t *f, ap_bucket_brigade **saveto,
|
|||||||
ap_bucket_brigade **b)
|
ap_bucket_brigade **b)
|
||||||
{
|
{
|
||||||
ap_bucket *e;
|
ap_bucket *e;
|
||||||
|
apr_pool_t *p = f->r ? f->r->pool : f->c->pool;
|
||||||
|
|
||||||
/* If have never stored any data in the filter, then we had better
|
/* If have never stored any data in the filter, then we had better
|
||||||
* create an empty bucket brigade so that we can concat.
|
* create an empty bucket brigade so that we can concat.
|
||||||
*/
|
*/
|
||||||
if (!(*saveto)) {
|
if (!(*saveto)) {
|
||||||
*saveto = ap_brigade_create(f->r->pool);
|
*saveto = ap_brigade_create(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
AP_RING_FOREACH(e, &(*b)->list, ap_bucket, link) {
|
AP_RING_FOREACH(e, &(*b)->list, ap_bucket, link) {
|
||||||
|
Reference in New Issue
Block a user