On Jun 26, 2008, at 9:48 AM, Kiffin Gish wrote:
Thanks Brian, I've tried what you suggested but it doesn't seem to work.
Could you be more specific? Here's what I've tried:

void register_hooks(apr_pool_t *p)
{
    ap_hook_translate_name(hook_translate_name, NULL, NULL,
APR_HOOK_REALLY_FIRST);
    ap_hook_pre_connection(hook_pre_connection, NULL, NULL,
APR_HOOK_MIDDLE);
ap_register_output_filter("wms-error-http-header", wmserror_ofilter,
            NULL, AP_FTYPE_CONNECTION) ;
}

static int hook_translate_name (request_rec *r)
{
    apr_table_setn(r->notes, "MY_NOTE", ".");
    ap_custom_response(r, HTTP_INTERNAL_SERVER_ERROR, xml);
    return HTTP_INTERNAL_SERVER_ERROR;
}

static int hook_pre_connection(conn_rec *c, void *csd)
{
    ap_add_output_filter("wms-error-httpd-header", NULL, NULL, c);
    return OK;
}

int wmserror_ofilter(ap_filter_t* f, apr_bucket_brigade* bb)
{
    const char *t = apr_table_get(f->r->notes, "MY_NOTE");
    if (t != NULL) { ap_set_content_type(f->r, "text/xml"); }
    return ap_pass_brigade(f->next, bb) ;
}


My guess would be you can't use ap_set_content_type in your filter, you will have to examine the buckets, find Conetent-Type and change it to text/xml.

Below is a quick hack I created from code we use to remove the server header and insert the host comment. It may not work perfectly out of the box, but by adding some log lines you should be able to get it working.

This also assume the headers will fit in a 8k brigade.

Brian



/* Because strnstr is not on RHEL4 */
static char *__strnstr(const char *big, const char *little, size_t len)
{
    size_t little_len = strlen(little);
    size_t i;
    for (i = 0; i <= len - little_len; i++) {
        if (memcmp(big + i, little, little_len) == 0) {
            return (char *)(big + i);
        }
    }

    return 0;
}

static apr_status_t wmserror_output_filter(ap_filter_t *f, apr_bucket_brigade *in)
{
  if (f->r != NULL && apr_table_get(f->r->notes, "MY_NOTE") != NULL) {

    apr_bucket *b;

for (b = APR_BRIGADE_FIRST(in); b != APR_BRIGADE_SENTINEL(in) && done == 0; b = APR_BUCKET_NEXT(b)) {
      const char *buf;
      size_t bytes ;

      if (!(APR_BUCKET_IS_METADATA(b))) {
if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS) {
          char *ct_header = __strnstr(buf, "Content-Type: ", bytes);
          char *end;
if (cl_header != NULL && (end = strstr(ct_header, "\n")) != NULL) {
            apr_bucket *newb = NULL;
            apr_bucket *new_ct;

            /* split off buffer at the ct header */
            apr_bucket_split(b, ct_header +  14 - buf);

            /* skip to the ct value bucket */
            b = APR_BUCKET_NEXT(b);

            /* split off after value */
            apr_bucket_split(b, end - ct_header + 14 + 1);

            /* skip to the next one */
            newb = APR_BUCKET_NEXT(b);

            /* remove it */
            APR_BUCKET_REMOVE(b);

            /* nuke it */
            apr_bucket_destroy(b);

            b = newb;

            /* I think this is the right function */
new_ct = apr_bucket_immortal_create("text/xml", sizeof("text/xml"), f->c->bucket_alloc);

            APR_BUCKET_INSERT_BEFORE(b, new_ct);

            apr_table_unset(f->r->notes, "MY_NOTE");
            break;
          }
        }
      }
    }
  }

  /* send the data up the stack */
  return ap_pass_brigade(f->next,in);
}



static void wmserror_insert_output_filter(request_rec *r)
{
ap_add_output_filter("WMSERROR_OUTPUT_FILTER", NULL, r, r- >connection);
}

static void register_hooks(apr_pool_t *p)
{
ap_register_output_filter("WMSERROR_OUTPUT_FILTER", wmserror_output_filter, NULL, AP_FTYPE_PROTOCOL);

ap_hook_insert_filter(wmserror_insert_output_filter, NULL, NULL, APR_HOOK_REALLY_LAST);
}






On Thu, 2008-06-26 at 08:35 -0400, Brian J. France wrote:
> On Jun 26, 2008, at 3:33 AM, Kiffin Gish wrote:
> > In order to reply with my own xml error, I want to use
> > ap_custom_response(r, HTTP_INTERNAL_SERVER_ERROR, xml);
> >
> > However, default content type is "text/html". If I try to change it by
> > using ap_set_content_type(r, "text/xml"), this has no effect.
> >
> > Is there anyone out there who can help me?
> >
>
> Ran into the same thing with apache 1.3. We have a patch that adds a
> custom hook that is called before headers are sent and we can re-set
> it back to text/xml there (remember this is 1.3).
>
> You could call ap_custom_response, set a flag in r->notes, have a
> output filter in your module that checks r->notes and if the flag set
> it scans for Content-type and resets it to text/xml.
>
> Brian
>
--
Kiffin Gish | Desktop & Services Development | TomTom | [EMAIL PROTECTED] | +31 (0) 6 15529214 mobile | +31 (0) 20 757 5000 office

Reply via email to