Brian,

This is great, thanks alot!

I've 'almost' got it working correctly, the only problem being that the
Content-Type is not getting truncated correctly, e.g. instead of:

Content-Type: text/xml\n
\n
<?xml version='1.0' encoding="UTF-8" standalone="no" ?>\n


I'm getting this:

Content-Type: text/xml<?xml version='1.0' encoding="UTF-8"
standalone="no" ?>\n

Any tips would be greatly appreciated.


On Thu, 2008-06-26 at 10:29 -0400, Brian J. France wrote:
> 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
> 
-- 
Kiffin Gish | Desktop & Services Development | TomTom | [EMAIL PROTECTED] | +31 
(0) 6 15529214 mobile | +31 (0) 20 757 5000 office


This e-mail message contains information which is confidential and may be 
privileged. It is intended for use by the addressee only. If you are not the 
intended addressee, we request that you notify the sender immediately and 
delete or destroy this e-mail message and any attachment(s), without copying, 
saving, forwarding, disclosing or using its contents in any other way. TomTom 
N.V., TomTom International BV or any other company belonging to the TomTom 
group of companies will not be liable for damage relating to the communication 
by e-mail of data, documents or any other information.

Reply via email to