You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Steve Hay <St...@planit.com> on 2010/03/11 15:18:08 UTC

Setting Content-Type in a custom response (mp2)

I have a mod_perl-2 handler that uses custom_response() to display error
messages if something goes wrong:

$r->custom_response(Apache2::Const::SERVER_ERROR, $error);
return Apache2::Const::SERVER_ERROR;

That almost works fine, but the trouble is that the Content-Type header
is always set to "text/html; charset=iso-8859-1", in which the charset,
at least, is potentially wrong: all the pages in my software produce
UTF-8 and are normally output with Content-Type "application/xhtml+xml;
charset=utf-8".

How do I set the Content-Type when issuing a custom_reponse()? The usual
thing of calling

$r->content_type("application/xhtml+xml; charset=utf-8");

doesn't seem to work in this case.

RE: Setting Content-Type in a custom response (mp2)

Posted by Andreas Mock <An...@web.de>.
Hi all,

I searched for that solution for hours not finding any until
Torsten posted this one.

IMHO it's worth it to put Torsten's snippet to the documentation
pages of mod_perl.

Even the book 'mod_perl 2 user's guide' leaves a big hole
in that area.

Thank you Torsten!

Best regards
Andreas Mock



-----Ursprüngliche Nachricht-----
Von: Steve Hay 
Gesendet: 12.03.2010 10:58:15
An: "Torsten Förtsch" <to...@gmx.net>,modperl@perl.apache.org
Betreff: RE: Setting Content-Type in a custom response (mp2)

>Torsten Förtsch wrote on 2010-03-11:
>> On Thursday 11 March 2010 15:18:08 Steve Hay wrote:
>>> I have a mod_perl-2 handler that uses custom_response() to display
>>> error messages if something goes wrong:
>>> 
>>> $r->custom_response(Apache2::Const::SERVER_ERROR, $error);
>>> return Apache2::Const::SERVER_ERROR;
>>> 
>>> That almost works fine, but the trouble is that the Content-Type header
>>> is always set to "text/html; charset=iso-8859-1", in which the charset,
>>> at least, is potentially wrong: all the pages in my software produce
>>> UTF-8 and are normally output with Content-Type "application/xhtml+xml;
>>> charset=utf-8".
>>> 
>>> How do I set the Content-Type when issuing a custom_reponse()? The
>>> usual thing of calling
>>> 
>>> $r->content_type("application/xhtml+xml; charset=utf-8");
>>> 
>>> doesn't seem to work in this case.
>>> 
>> I think that is impossible. ap_send_error_response() contains this code:
>> 
>>         if (apr_table_get(r->subprocess_env,
>>                           "suppress-error-charset") != NULL) {
>>             core_request_config *request_conf =
>>                         ap_get_module_config(r->request_config,
>> &core_module);
>>             request_conf->suppress_charset = 1; /* avoid adding default
>>                                                  * charset later
>>                                                  */
>>             ap_set_content_type(r, "text/html");
>>         }
>>         else {
>>             ap_set_content_type(r, "text/html; charset=iso-8859-1");
>>         }
>>  The resulting content-type is either "text/html; charset=iso-8859-1" or
>> "text/html".
>> 
>> But instead of passing the response text directly to $r-
>>> custom_response you
>> can specify an URL. ap_die() will then create an internal redirect to
>> this URL. Via $r->prev->pnotes you can then access the pnotes of the
>> failed request. Putting all together a solution could look like:
>> 
>>   $r->pnotes->{estring}=$error;
>>   $r->pnotes->{ect}='my/special-content-type'; # use an otherwise not
>>   used URL here $r->custom_response(Apache2::Const::SERVER_ERROR,
>>   '/-/error');
>>   
>>   <Location /-/error>
>>     SetHandler modperl
>>     # please insert a \ at the end of each of the following lines
>>     # up to }"
>>     PerlResponseHandler "sub {
>>       my ($r)=@_; return Apache2::Const::NOT_FOUND unless $r->prev;
>>       $r->content_type($r->prev->pnotes->{ect});
>>       $r->print($r->prev->pnotes->{estring}); return Apache2::Const::OK;
>>     }"
>>   </Location>
>> 
>
>Thanks! That works a treat :-)

RE: Setting Content-Type in a custom response (mp2)

Posted by Steve Hay <St...@planit.com>.
Torsten Förtsch wrote on 2010-03-11:
> On Thursday 11 March 2010 15:18:08 Steve Hay wrote:
>> I have a mod_perl-2 handler that uses custom_response() to display
>> error messages if something goes wrong:
>> 
>> $r->custom_response(Apache2::Const::SERVER_ERROR, $error);
>> return Apache2::Const::SERVER_ERROR;
>> 
>> That almost works fine, but the trouble is that the Content-Type header
>> is always set to "text/html; charset=iso-8859-1", in which the charset,
>> at least, is potentially wrong: all the pages in my software produce
>> UTF-8 and are normally output with Content-Type "application/xhtml+xml;
>> charset=utf-8".
>> 
>> How do I set the Content-Type when issuing a custom_reponse()? The
>> usual thing of calling
>> 
>> $r->content_type("application/xhtml+xml; charset=utf-8");
>> 
>> doesn't seem to work in this case.
>> 
> I think that is impossible. ap_send_error_response() contains this code:
> 
>         if (apr_table_get(r->subprocess_env,
>                           "suppress-error-charset") != NULL) {
>             core_request_config *request_conf =
>                         ap_get_module_config(r->request_config,
> &core_module);
>             request_conf->suppress_charset = 1; /* avoid adding default
>                                                  * charset later
>                                                  */
>             ap_set_content_type(r, "text/html");
>         }
>         else {
>             ap_set_content_type(r, "text/html; charset=iso-8859-1");
>         }
>  The resulting content-type is either "text/html; charset=iso-8859-1" or
> "text/html".
> 
> But instead of passing the response text directly to $r-
>> custom_response you
> can specify an URL. ap_die() will then create an internal redirect to
> this URL. Via $r->prev->pnotes you can then access the pnotes of the
> failed request. Putting all together a solution could look like:
> 
>   $r->pnotes->{estring}=$error;
>   $r->pnotes->{ect}='my/special-content-type'; # use an otherwise not
>   used URL here $r->custom_response(Apache2::Const::SERVER_ERROR,
>   '/-/error');
>   
>   <Location /-/error>
>     SetHandler modperl
>     # please insert a \ at the end of each of the following lines
>     # up to }"
>     PerlResponseHandler "sub {
>       my ($r)=@_; return Apache2::Const::NOT_FOUND unless $r->prev;
>       $r->content_type($r->prev->pnotes->{ect});
>       $r->print($r->prev->pnotes->{estring}); return Apache2::Const::OK;
>     }"
>   </Location>
> 

Thanks! That works a treat :-)

Re: Setting Content-Type in a custom response (mp2)

Posted by Torsten Förtsch <to...@gmx.net>.
On Thursday 11 March 2010 15:18:08 Steve Hay wrote:
> I have a mod_perl-2 handler that uses custom_response() to display error
> messages if something goes wrong:
> 
> $r->custom_response(Apache2::Const::SERVER_ERROR, $error);
> return Apache2::Const::SERVER_ERROR;
> 
> That almost works fine, but the trouble is that the Content-Type header
> is always set to "text/html; charset=iso-8859-1", in which the charset,
> at least, is potentially wrong: all the pages in my software produce
> UTF-8 and are normally output with Content-Type "application/xhtml+xml;
> charset=utf-8".
> 
> How do I set the Content-Type when issuing a custom_reponse()? The usual
> thing of calling
> 
> $r->content_type("application/xhtml+xml; charset=utf-8");
> 
> doesn't seem to work in this case.
> 
I think that is impossible. ap_send_error_response() contains this code:

        if (apr_table_get(r->subprocess_env,
                          "suppress-error-charset") != NULL) {
            core_request_config *request_conf =
                        ap_get_module_config(r->request_config, &core_module);
            request_conf->suppress_charset = 1; /* avoid adding default
                                                 * charset later
                                                 */
            ap_set_content_type(r, "text/html");
        }
        else {
            ap_set_content_type(r, "text/html; charset=iso-8859-1");
        }

The resulting content-type is either "text/html; charset=iso-8859-1" or 
"text/html".

But instead of passing the response text directly to $r->custom_response you 
can specify an URL. ap_die() will then create an internal redirect to this 
URL. Via $r->prev->pnotes you can then access the pnotes of the failed 
request. Putting all together a solution could look like:

  $r->pnotes->{estring}=$error;
  $r->pnotes->{ect}='my/special-content-type';
  # use an otherwise not used URL here
  $r->custom_response(Apache2::Const::SERVER_ERROR, '/-/error');

  <Location /-/error>
    SetHandler modperl
    # please insert a \ at the end of each of the following lines 
    # up to }"
    PerlResponseHandler "sub {
      my ($r)=@_;
      return Apache2::Const::NOT_FOUND unless $r->prev;
      $r->content_type($r->prev->pnotes->{ect});
      $r->print($r->prev->pnotes->{estring});
      return Apache2::Const::OK;
    }"
  </Location>

Torsten Förtsch

-- 
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net