1 package Catalyst::View::ContentNegotiation::XHTML;
4 use MooseX::Types::Moose qw/Num Str ArrayRef/;
5 use MooseX::Types::Structured qw/Tuple/;
6 use HTTP::Negotiate qw/choose/;
8 use namespace::clean -except => 'meta';
10 # Remember to bump $VERSION in View::TT::XHTML also.
11 our $VERSION = '1.100';
17 isa => ArrayRef[Tuple[Str, Num, Str]],
19 builder => '_build_variants',
24 [qw| xhtml 1.000 application/xhtml+xml |],
25 [qw| html 0.900 text/html |],
29 after process => sub {
31 if ( my $accept = $self->pragmatic_accept($c) and $c->response->headers->{'content-type'} =~ m|text/html|) {
32 my $headers = $c->request->headers->clone;
33 $headers->header('Accept' => $accept);
34 if ( choose($self->variants, $headers) eq 'xhtml') {
35 $c->response->headers->{'content-type'} =~ s|text/html|application/xhtml+xml|;
40 sub pragmatic_accept {
42 my $accept = $c->request->header('Accept') or return;
43 if ($accept =~ m|text/html|) {
44 $accept =~ s!\*/\*\s*([,]+|$)!*/*;q=0.5$1!;
47 $accept =~ s!\*/\*\s*([,]+|$)!text/html,*/*;q=0.5$1!;
58 Catalyst::View::ContentNegotiation::XHTML - Adjusts the
59 response Content-Type header to application/xhtml+xml
60 if the browser accepts it.
64 package Catalyst::View::TT;
67 use namespace::clean -except => 'meta';
69 extends qw/Catalyst::View::TT/;
70 with qw/Catalyst::View::ContentNegotiation::XHTML/;
76 This is a simple Role which sets the response C<Content-Type> to be
77 C<application/xhtml+xml> if the users browser sends an C<Accept> header
78 indicating that it is willing to process that MIME type.
80 Changing the C<Content-Type> to C<application/xhtml+xml> causes
81 browsers to interpret the page as XML, meaning that your markup must
86 This is useful when you're developing your application, as you know that
87 all pages you view are parsed as XML, so any errors caused by your markup
88 not being well-formed will show up at once.
90 Whilst this module is has been tested against most popular browsers including
91 Internet Explorer, it may cause unexpected results on browsers which do not
92 properly support the C<application/xhtml+xml> MIME type.
94 =head1 METHOD MODIFIERS
98 Changes the response C<Content-Type> if appropriate (from the requests C<Accept> header).
102 =head2 pragmatic_accept
104 Some browsers (such as Internet Explorer) have a nasty way of sending
105 Accept */* and this claiming to support XHTML just as well as HTML.
106 Saving to a file on disk or opening with another application does
107 count as accepting, but it really should have a lower q value then
108 text/html. This sub takes a pragmatic approach and corrects this mistake
109 by modifying the Accept header before passing it to content negotiation.
115 Returns an array ref of 3 part arrays, comprising name, priority, output
116 mime-type, which is used for the content negotiation algorithm.
118 =head1 PRIVATE METHODS
120 =head2 _build_variants
122 Returns the default variant attribute contents.
128 =item L<Catalyst::View::TT::XHTML> - Trivial Catalyst TT view using this role.
130 =item L<http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html> - Content negotiation RFC.
136 Should be split into a base ContentNegotiation role which is consumed by ContentNegotiation::XHTML.
140 Tomas Doran (t0m) C<< <bobtfish@bobtfish.net> >>
146 =item David Dorward - test patches and */* pragmatism.
148 =item Florian Ragwitz (rafl) C<< <rafl@debian.org> >> - Conversion into a Moose Role
154 This module itself is copyright (c) 2008 Tomas Doran and is licensed under the same terms as Perl itself.