httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Brian J. France" <l...@firehawksystems.com>
Subject Re: ap_custom_response content type 'text/xml'
Date Thu, 26 Jun 2008 14:29:03 GMT

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 | kiffin.gish@tomtom.com 
>  | +31 (0) 6 15529214 mobile | +31 (0) 20 757 5000 office


Mime
View raw message